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 53static int 54sysctl_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 103static int 104sysctl_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 153static int 154sysctl_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 178static int 179sysctl_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 198static int 199sysctl_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 218static int 219sysctl_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 */ 243static int 244kperf_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 */ 277SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 278 "kperf"); 279 280/* action sub-section */ 281SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 282 "action"); 283 284SYSCTL_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 289SYSCTL_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 */ 296SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW|CTLFLAG_LOCKED, 0, 297 "timer"); 298 299SYSCTL_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 304SYSCTL_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 309SYSCTL_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 */ 315SYSCTL_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 320int legacy_mode = 1; 321SYSCTL_INT(_kperf, OID_AUTO, legacy_mode, CTLFLAG_RW, &legacy_mode, 0, "legacy_mode"); 322 323#if 0 324SYSCTL_PROC(_kperf, OID_AUTO, timer_period, 325 CTLFLAG_RW, (void*)REQ_TIMER, 326 sizeof(uint64_t), kperf_sysctl, "QU", "nanoseconds"); 327 328SYSCTL_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 */ 333SYSCTL_INT(_kperf, OID_AUTO, filter_pid0, 334 CTLFLAG_RW, &pid_list[0], 0, ""); 335SYSCTL_INT(_kperf, OID_AUTO, filter_pid1, 336 CTLFLAG_RW, &pid_list[1], 0, ""); 337SYSCTL_INT(_kperf, OID_AUTO, filter_pid2, 338 CTLFLAG_RW, &pid_list[2], 0, ""); 339SYSCTL_INT(_kperf, OID_AUTO, filter_pid3, 340 CTLFLAG_RW, &pid_list[3], 0, ""); 341 342#endif 343