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#include <mach/mach_types.h> 29#include <kern/thread.h> 30#include <kern/machine.h> 31#include <kern/kalloc.h> 32#include <sys/errno.h> 33 34#include <kperf/filter.h> 35#include <kperf/sample.h> 36#include <kperf/kperfbsd.h> 37#include <kperf/pet.h> 38#include <kperf/action.h> 39#include <kperf/kperf.h> 40#include <kperf/timetrigger.h> 41 42/** misc functions **/ 43#include <chud/chud_xnu.h> /* XXX: should bust this out */ 44 45static struct kperf_sample *intr_samplev = NULL; 46static unsigned intr_samplec = 0; 47static unsigned sampling_status = KPERF_SAMPLING_OFF; 48static unsigned kperf_initted = 0; 49 50 51extern void (*chudxnu_thread_ast_handler)(thread_t); 52 53struct kperf_sample* 54kperf_intr_sample_buffer(void) 55{ 56 unsigned ncpu = chudxnu_cpu_number(); 57 58 // XXX: assert? 59 if( ncpu >= intr_samplec ) 60 return NULL; 61 62 return &intr_samplev[ncpu]; 63} 64 65/* setup interrupt sample buffers */ 66int 67kperf_init(void) 68{ 69 unsigned ncpus = 0; 70 71 if( kperf_initted ) 72 return 0; 73 74 /* get number of cpus */ 75 ncpus = machine_info.logical_cpu_max; 76 77 /* make the CPU array 78 * FIXME: cache alignment 79 */ 80 intr_samplev = kalloc( ncpus * sizeof(*intr_samplev)); 81 82 if( intr_samplev == NULL ) 83 return ENOMEM; 84 85 /* clear it */ 86 bzero( intr_samplev, ncpus * sizeof(*intr_samplev) ); 87 88 chudxnu_thread_ast_handler = kperf_thread_ast_handler; 89 90 /* we're done */ 91 intr_samplec = ncpus; 92 kperf_initted = 1; 93 94 return 0; 95} 96 97 98/** kext start/stop functions **/ 99kern_return_t kperf_start (kmod_info_t * ki, void * d); 100 101kern_return_t 102kperf_start (kmod_info_t * ki, void * d) 103{ 104 (void) ki; 105 (void) d; 106 107 /* say hello */ 108 printf( "aprof: kext starting\n" ); 109 110 /* register modules */ 111 // kperf_action_init(); 112 kperf_filter_init(); 113 kperf_pet_init(); 114 115 /* register the sysctls */ 116 //kperf_register_profiling(); 117 118 return KERN_SUCCESS; 119} 120 121 122/* random misc-ish functions */ 123uint32_t 124kperf_get_thread_bits( thread_t thread ) 125{ 126 return thread->t_chud; 127} 128 129void 130kperf_set_thread_bits( thread_t thread, uint32_t bits ) 131{ 132 thread->t_chud = bits; 133} 134 135/* mark an AST to fire on a thread */ 136void 137kperf_set_thread_ast( thread_t thread ) 138{ 139 /* FIXME: only call this on current thread from an interrupt 140 * handler for now... 141 */ 142 if( thread != current_thread() ) 143 panic( "unsafe AST set" ); 144 145 act_set_kperf(thread); 146} 147 148unsigned 149kperf_sampling_status(void) 150{ 151 return sampling_status; 152} 153 154int 155kperf_sampling_enable(void) 156{ 157 /* already running! */ 158 if( sampling_status == KPERF_SAMPLING_ON ) 159 return 0; 160 161 if ( sampling_status != KPERF_SAMPLING_OFF ) 162 panic( "kperf: sampling wasn't off" ); 163 164 /* make sure interrupt tables and actions are initted */ 165 if( !kperf_initted 166 || (kperf_action_get_count() == 0) ) 167 return ECANCELED; 168 169 /* mark as running */ 170 sampling_status = KPERF_SAMPLING_ON; 171 172 /* tell timers to enable */ 173 kperf_timer_go(); 174 175 return 0; 176} 177 178int 179kperf_sampling_disable(void) 180{ 181 if( sampling_status != KPERF_SAMPLING_ON ) 182 return 0; 183 184 /* mark a shutting down */ 185 sampling_status = KPERF_SAMPLING_SHUTDOWN; 186 187 /* tell timers to disable */ 188 kperf_timer_stop(); 189 190 /* mark as off */ 191 sampling_status = KPERF_SAMPLING_OFF; 192 193 return 0; 194} 195