|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: * ! 25: */ ! 26: /* ! 27: * File: etap.c ! 28: */ ! 29: ! 30: #include <cpus.h> ! 31: #include <kern/lock.h> ! 32: #include <kern/etap_macros.h> ! 33: #include <kern/misc_protos.h> ! 34: #include <kern/host.h> ! 35: #include <types.h> ! 36: #include <mach/kern_return.h> ! 37: #include <mach/port.h> ! 38: #include <vm/vm_map.h> ! 39: #include <vm/vm_kern.h> /* for kernel_map, ipc_kernel_map */ ! 40: #if ETAP_MONITOR ! 41: #include <machine/machine_tables.h> ! 42: #include <mach/bootstrap_server.h> ! 43: #include <mach/clock.h> ! 44: #include <mach/clock_reply.h> ! 45: #include <mach/default_pager_object.h> ! 46: #include <device/device.h> ! 47: #include <device/device_reply.h> ! 48: #include <device/device_request.h> ! 49: #include <mach_debug/mach_debug.h> ! 50: /*#include <mach/mach_host.h>*/ ! 51: #include <mach/mach_norma.h> ! 52: #include <mach/mach_port.h> ! 53: #include <mach/memory_object_default.h> ! 54: #include <mach/memory_object_user.h> ! 55: #include <mach/notify_server.h> ! 56: #include <mach/prof.h> ! 57: #include <machine/unix_map.h> ! 58: #endif ! 59: #if MACH_KDB ! 60: #include <ddb/db_output.h> ! 61: #include <ddb/db_sym.h> ! 62: #include <ddb/db_command.h> ! 63: #if 0 /* WHY?? */ ! 64: #include <i386/ipl.h> ! 65: #endif ! 66: #endif ! 67: ! 68: /* ! 69: * Forwards ! 70: */ ! 71: ! 72: kern_return_t ! 73: etap_get_info(host_t, int*, int*, vm_offset_t*, vm_offset_t*, ! 74: int*, int*, int*, int*); ! 75: ! 76: kern_return_t ! 77: etap_mon_reconfig(host_t, int); ! 78: ! 79: kern_return_t ! 80: etap_new_probe(host_t, vm_address_t, vm_size_t, boolean_t, vm_address_t); ! 81: ! 82: kern_return_t ! 83: etap_trace_thread(thread_act_t, boolean_t); ! 84: ! 85: void ! 86: etap_trace_reset(int); ! 87: ! 88: void ! 89: etap_interrupt_probe(int, int); ! 90: ! 91: void ! 92: etap_machcall_probe1(int); ! 93: ! 94: void ! 95: etap_machcall_probe2(void); ! 96: ! 97: void ! 98: etap_print(void); ! 99: ! 100: ! 101: #if ETAP ! 102: ! 103: #ifndef max ! 104: #define max(x,y) ((x > y) ? x : y) ! 105: #endif /* max */ ! 106: ! 107: event_table_t ! 108: etap_event_table_find(etap_event_t); ! 109: ! 110: /* ======================= ! 111: * ETAP Lock definitions ! 112: * ======================= ! 113: */ ! 114: ! 115: #if ETAP_LOCK_TRACE ! 116: #define etap_lock simple_lock_no_trace ! 117: #define etap_unlock simple_unlock_no_trace ! 118: #else /* ETAP_LOCK_TRACE */ ! 119: #define etap_lock simple_lock ! 120: #define etap_unlock simple_unlock ! 121: #endif /* ETAP_LOCK_TRACE */ ! 122: ! 123: #define event_table_lock() etap_lock(&event_table_lock) ! 124: #define event_table_unlock() etap_unlock(&event_table_lock) ! 125: ! 126: #define cumulative_buffer_lock(s) \ ! 127: MACRO_BEGIN \ ! 128: s = splhigh(); \ ! 129: etap_lock(&cbuff_lock); \ ! 130: MACRO_END ! 131: ! 132: #define cumulative_buffer_unlock(s) \ ! 133: MACRO_BEGIN \ ! 134: etap_unlock(&cbuff_lock); \ ! 135: splx(s); \ ! 136: MACRO_END ! 137: ! 138: ! 139: #if ETAP_LOCK_ACCUMULATE ! 140: ! 141: /* ======================================== ! 142: * ETAP Cumulative lock trace definitions ! 143: * ======================================== ! 144: */ ! 145: ! 146: int cbuff_width = ETAP_CBUFF_WIDTH; ! 147: ! 148: /* ! 149: * Cumulative buffer declaration ! 150: * ! 151: * For both protection and mapping purposes, the cumulative ! 152: * buffer must be aligned on a page boundary. Since the cumulative ! 153: * buffer must be statically defined, page boundary alignment is not ! 154: * garenteed. Instead, the buffer is allocated with 2 extra pages. ! 155: * The cumulative buffer pointer will round up to the nearest page. ! 156: * ! 157: * This will garentee page boundary alignment. ! 158: */ ! 159: ! 160: #define TWO_PAGES 16384 /* XXX does this apply ??*/ ! 161: #define CBUFF_ALLOCATED_SIZE sizeof(struct cumulative_buffer)+TWO_PAGES ! 162: ! 163: decl_simple_lock_data (,cbuff_lock) ! 164: #if MACH_LDEBUG ! 165: simple_lock_t cbuff_locks; ! 166: #else ! 167: simple_lock_data_t cbuff_locks; ! 168: #endif ! 169: char cbuff_allocated [CBUFF_ALLOCATED_SIZE]; ! 170: cumulative_buffer_t cbuff = {0}; ! 171: ! 172: #endif /* ETAP_LOCK_ACCUMULATE */ ! 173: ! 174: #if ETAP_MONITOR ! 175: ! 176: int mbuff_entries = ETAP_MBUFF_ENTRIES; ! 177: ! 178: /* ! 179: * Create an array of pointers to monitor buffers. ! 180: * The buffers themselves are allocated at run-time. ! 181: */ ! 182: ! 183: struct monitor_buffer *mbuff[NCPUS]; ! 184: #endif /* ETAP_MONITOR */ ! 185: ! 186: /* ========================== ! 187: * Event table declarations ! 188: * ========================== ! 189: */ ! 190: ! 191: decl_simple_lock_data(,event_table_lock) ! 192: ! 193: const struct event_table_entry event_table_init[] = ! 194: { ! 195: ! 196: /*-----------------------------------------------------------------------* ! 197: * ETAP EVENT TRACE STATUS TEXT NAME DYNAMIC * ! 198: *-----------------------------------------------------------------------*/ ! 199: ! 200: #if ETAP_EVENT_MONITOR ! 201: {ETAP_P_USER_EVENT0 , ETAP_TRACE_OFF , "p_user_event0" , STATIC}, ! 202: {ETAP_P_USER_EVENT1 , ETAP_TRACE_OFF , "p_user_event1" , STATIC}, ! 203: {ETAP_P_USER_EVENT2 , ETAP_TRACE_OFF , "p_user_event2" , STATIC}, ! 204: {ETAP_P_USER_EVENT3 , ETAP_TRACE_OFF , "p_user_event3" , STATIC}, ! 205: {ETAP_P_USER_EVENT4 , ETAP_TRACE_OFF , "p_user_event4" , STATIC}, ! 206: {ETAP_P_USER_EVENT5 , ETAP_TRACE_OFF , "p_user_event5" , STATIC}, ! 207: {ETAP_P_USER_EVENT6 , ETAP_TRACE_OFF , "p_user_event6" , STATIC}, ! 208: {ETAP_P_USER_EVENT7 , ETAP_TRACE_OFF , "p_user_event7" , STATIC}, ! 209: {ETAP_P_USER_EVENT8 , ETAP_TRACE_OFF , "p_user_event8" , STATIC}, ! 210: {ETAP_P_USER_EVENT9 , ETAP_TRACE_OFF , "p_user_event9" , STATIC}, ! 211: {ETAP_P_USER_EVENT10 , ETAP_TRACE_OFF , "p_user_event10" , STATIC}, ! 212: {ETAP_P_USER_EVENT11 , ETAP_TRACE_OFF , "p_user_event11" , STATIC}, ! 213: {ETAP_P_USER_EVENT12 , ETAP_TRACE_OFF , "p_user_event12" , STATIC}, ! 214: {ETAP_P_USER_EVENT13 , ETAP_TRACE_OFF , "p_user_event13" , STATIC}, ! 215: {ETAP_P_USER_EVENT14 , ETAP_TRACE_OFF , "p_user_event14" , STATIC}, ! 216: {ETAP_P_USER_EVENT15 , ETAP_TRACE_OFF , "p_user_event15" , STATIC}, ! 217: {ETAP_P_USER_EVENT16 , ETAP_TRACE_OFF , "p_user_event16" , STATIC}, ! 218: {ETAP_P_USER_EVENT17 , ETAP_TRACE_OFF , "p_user_event17" , STATIC}, ! 219: {ETAP_P_USER_EVENT18 , ETAP_TRACE_OFF , "p_user_event18" , STATIC}, ! 220: {ETAP_P_USER_EVENT19 , ETAP_TRACE_OFF , "p_user_event19" , STATIC}, ! 221: {ETAP_P_USER_EVENT20 , ETAP_TRACE_OFF , "p_user_event20" , STATIC}, ! 222: {ETAP_P_USER_EVENT21 , ETAP_TRACE_OFF , "p_user_event21" , STATIC}, ! 223: {ETAP_P_USER_EVENT22 , ETAP_TRACE_OFF , "p_user_event22" , STATIC}, ! 224: {ETAP_P_USER_EVENT23 , ETAP_TRACE_OFF , "p_user_event23" , STATIC}, ! 225: {ETAP_P_USER_EVENT24 , ETAP_TRACE_OFF , "p_user_event24" , STATIC}, ! 226: {ETAP_P_USER_EVENT25 , ETAP_TRACE_OFF , "p_user_event25" , STATIC}, ! 227: {ETAP_P_USER_EVENT26 , ETAP_TRACE_OFF , "p_user_event26" , STATIC}, ! 228: {ETAP_P_USER_EVENT27 , ETAP_TRACE_OFF , "p_user_event27" , STATIC}, ! 229: {ETAP_P_USER_EVENT28 , ETAP_TRACE_OFF , "p_user_event28" , STATIC}, ! 230: {ETAP_P_USER_EVENT29 , ETAP_TRACE_OFF , "p_user_event29" , STATIC}, ! 231: {ETAP_P_USER_EVENT30 , ETAP_TRACE_OFF , "p_user_event30" , STATIC}, ! 232: {ETAP_P_USER_EVENT31 , ETAP_TRACE_OFF , "p_user_event31" , STATIC}, ! 233: {ETAP_P_SYSCALL_MACH , ETAP_TRACE_OFF , "p_syscall_mach" , STATIC}, ! 234: {ETAP_P_SYSCALL_UNIX , ETAP_TRACE_OFF , "p_syscall_unix" , STATIC}, ! 235: {ETAP_P_THREAD_LIFE , ETAP_TRACE_OFF , "p_thread_life" , STATIC}, ! 236: {ETAP_P_THREAD_CTX , ETAP_TRACE_OFF , "p_thread_ctx" , STATIC}, ! 237: {ETAP_P_RPC , ETAP_TRACE_OFF , "p_rpc" , STATIC}, ! 238: {ETAP_P_INTERRUPT , ETAP_TRACE_OFF , "p_interrupt" , STATIC}, ! 239: {ETAP_P_ACT_ABORT , ETAP_TRACE_OFF , "p_act_abort" , STATIC}, ! 240: {ETAP_P_PRIORITY , ETAP_TRACE_OFF , "p_priority" , STATIC}, ! 241: {ETAP_P_EXCEPTION , ETAP_TRACE_OFF , "p_exception" , STATIC}, ! 242: {ETAP_P_DEPRESSION , ETAP_TRACE_OFF , "p_depression" , STATIC}, ! 243: {ETAP_P_MISC , ETAP_TRACE_OFF , "p_misc" , STATIC}, ! 244: {ETAP_P_DETAP , ETAP_TRACE_OFF , "p_detap" , STATIC}, ! 245: #endif /* ETAP_EVENT_MONITOR */ ! 246: ! 247: #if ETAP_LOCK_TRACE ! 248: {ETAP_VM_BUCKET , ETAP_TRACE_OFF , "vm_bucket" , STATIC},/**/ ! 249: {ETAP_VM_HIMEM , ETAP_TRACE_OFF , "vm_himem" , STATIC}, ! 250: {ETAP_VM_MAP , ETAP_TRACE_OFF , "vm_map" , 1}, ! 251: {ETAP_VM_MAP_I , ETAP_TRACE_OFF , "vm_map_i" , 2}, ! 252: {ETAP_VM_MEMMAN , ETAP_TRACE_OFF , "vm_memman" , STATIC},/**/ ! 253: {ETAP_VM_MSYNC , ETAP_TRACE_OFF , "vm_msync" , 3}, ! 254: {ETAP_VM_OBJ , ETAP_TRACE_OFF , "vm_obj" , 4}, ! 255: {ETAP_VM_OBJ_CACHE , ETAP_TRACE_OFF , "vm_obj_cache" , 5}, ! 256: {ETAP_VM_PAGE_ALLOC , ETAP_TRACE_OFF , "vm_page_alloc" , STATIC},/**/ ! 257: {ETAP_VM_PAGEOUT , ETAP_TRACE_OFF , "vm_pageout" , STATIC}, ! 258: {ETAP_VM_PAGEQ , ETAP_TRACE_OFF , "vm_pageq" , STATIC}, ! 259: {ETAP_VM_PAGEQ_FREE , ETAP_TRACE_OFF , "vm_pageq_free" , STATIC}, ! 260: {ETAP_VM_PMAP , ETAP_TRACE_OFF , "vm_pmap" , 6}, ! 261: {ETAP_VM_PMAP_CACHE , ETAP_TRACE_OFF , "vm_pmap_cache" , STATIC}, ! 262: {ETAP_VM_PMAP_FREE , ETAP_TRACE_OFF , "vm_pmap_free" , STATIC}, ! 263: {ETAP_VM_PMAP_KERNEL , ETAP_TRACE_OFF , "vm_pmap_kern" , STATIC}, ! 264: {ETAP_VM_PMAP_SYS , ETAP_TRACE_OFF , "vm_pmap_sys" , 7}, ! 265: {ETAP_VM_PMAP_SYS_I , ETAP_TRACE_OFF , "vm_pmap_sys_i" , 8}, ! 266: {ETAP_VM_PMAP_UPDATE , ETAP_TRACE_OFF , "vm_pmap_update" , STATIC}, ! 267: {ETAP_VM_PREPPIN , ETAP_TRACE_OFF , "vm_preppin" , STATIC}, ! 268: {ETAP_VM_RESULT , ETAP_TRACE_OFF , "vm_result" , 9}, ! 269: {ETAP_VM_TEST , ETAP_TRACE_OFF , "vm_tes" , STATIC},/**/ ! 270: {ETAP_VM_PMAP_PHYSENTRIES, ETAP_TRACE_OFF , "vm_pmap_physentries", STATIC}, ! 271: {ETAP_VM_PMAP_SID , ETAP_TRACE_OFF , "vm_pmap_sid" , STATIC}, ! 272: {ETAP_VM_PMAP_PTE , ETAP_TRACE_OFF , "vm_pmap_pte" , STATIC}, ! 273: {ETAP_VM_PMAP_PTE_OVFLW , ETAP_TRACE_OFF , "vm_pmap_pte_ovflw", STATIC}, ! 274: {ETAP_VM_PMAP_TLB , ETAP_TRACE_OFF , "vm_pmap_tlb" , STATIC}, ! 275: ! 276: {ETAP_IPC_IHGB , ETAP_TRACE_OFF , "ipc_ihgb" , 10},/**/ ! 277: {ETAP_IPC_IS , ETAP_TRACE_OFF , "ipc_is" , 11},/**/ ! 278: {ETAP_IPC_IS_REF , ETAP_TRACE_OFF , "ipc_is_ref" , 12},/**/ ! 279: {ETAP_IPC_MQUEUE , ETAP_TRACE_OFF , "ipc_mqueue" , STATIC},/**/ ! 280: {ETAP_IPC_OBJECT , ETAP_TRACE_OFF , "ipc_object" , STATIC},/**/ ! 281: {ETAP_IPC_PORT_MULT , ETAP_TRACE_OFF , "ipc_port_mult" , 13},/**/ ! 282: {ETAP_IPC_PORT_TIME , ETAP_TRACE_OFF , "ipc_port_time" , 14},/**/ ! 283: {ETAP_IPC_RPC , ETAP_TRACE_OFF , "ipc_rpc" , 15},/**/ ! 284: {ETAP_IPC_PORT_ALLOCQ , ETAP_TRACE_OFF , "ipc_port_allocq" , STATIC},/**/ ! 285: ! 286: {ETAP_IO_AHA , ETAP_TRACE_OFF , "io_aha" , STATIC}, ! 287: {ETAP_IO_CHIP , ETAP_TRACE_OFF , "io_chip" , STATIC}, ! 288: {ETAP_IO_DEV , ETAP_TRACE_OFF , "io_dev" , 16},/**/ ! 289: {ETAP_IO_DEV_NUM , ETAP_TRACE_OFF , "io_dev_num" , STATIC}, ! 290: {ETAP_IO_DEV_PAGEH , ETAP_TRACE_OFF , "io_dev_pageh" , STATIC},/**/ ! 291: {ETAP_IO_DEV_PAGER , ETAP_TRACE_OFF , "io_dev_pager" , STATIC},/**/ ! 292: {ETAP_IO_DEV_PORT , ETAP_TRACE_OFF , "io_dev_port" , STATIC},/**/ ! 293: {ETAP_IO_DEV_REF , ETAP_TRACE_OFF , "io_dev_new" , 17},/**/ ! 294: {ETAP_IO_DEVINS , ETAP_TRACE_OFF , "io_devins" , STATIC}, ! 295: {ETAP_IO_DONE_LIST , ETAP_TRACE_OFF , "io_done_list" , STATIC}, ! 296: {ETAP_IO_DONE_Q , ETAP_TRACE_OFF , "io_doneq" , 18}, ! 297: {ETAP_IO_DONE_REF , ETAP_TRACE_OFF , "io_done_ref" , 19}, ! 298: {ETAP_IO_EAHA , ETAP_TRACE_OFF , "io_eaha" , STATIC}, ! 299: {ETAP_IO_HD_PROBE , ETAP_TRACE_OFF , "io_hd_probe" , STATIC}, ! 300: {ETAP_IO_IOPB , ETAP_TRACE_OFF , "io_iopb" , STATIC}, ! 301: {ETAP_IO_KDQ , ETAP_TRACE_OFF , "io_kdq" , STATIC}, ! 302: {ETAP_IO_KDTTY , ETAP_TRACE_OFF , "io_kdtty" , STATIC}, ! 303: {ETAP_IO_REQ , ETAP_TRACE_OFF , "io_req" , 20}, ! 304: {ETAP_IO_TARGET , ETAP_TRACE_OFF , "io_target" , STATIC}, ! 305: {ETAP_IO_TTY , ETAP_TRACE_OFF , "io_tty" , STATIC}, ! 306: {ETAP_IO_IOP_LOCK , ETAP_TRACE_OFF , "io_iop" , STATIC},/**/ ! 307: {ETAP_IO_DEV_NAME , ETAP_TRACE_OFF , "io_dev_name" , STATIC},/**/ ! 308: {ETAP_IO_CDLI , ETAP_TRACE_OFF , "io_cdli" , STATIC},/**/ ! 309: {ETAP_IO_HIPPI_FILTER , ETAP_TRACE_OFF , "io_hippi_filter" , STATIC},/**/ ! 310: {ETAP_IO_HIPPI_SRC , ETAP_TRACE_OFF , "io_hippi_src" , STATIC},/**/ ! 311: {ETAP_IO_HIPPI_DST , ETAP_TRACE_OFF , "io_hippi_dst" , STATIC},/**/ ! 312: {ETAP_IO_HIPPI_PKT , ETAP_TRACE_OFF , "io_hippi_pkt" , STATIC},/**/ ! 313: {ETAP_IO_NOTIFY , ETAP_TRACE_OFF , "io_notify" , STATIC},/**/ ! 314: {ETAP_IO_DATADEV , ETAP_TRACE_OFF , "io_data_device" , STATIC},/**/ ! 315: {ETAP_IO_OPEN , ETAP_TRACE_OFF , "io_open" , STATIC}, ! 316: {ETAP_IO_OPEN_I , ETAP_TRACE_OFF , "io_open_i" , STATIC}, ! 317: ! 318: {ETAP_THREAD_ACT , ETAP_TRACE_OFF , "th_act" , 21}, ! 319: {ETAP_THREAD_ACTION , ETAP_TRACE_OFF , "th_action" , STATIC}, ! 320: {ETAP_THREAD_LOCK , ETAP_TRACE_OFF , "th_lock" , 22}, ! 321: {ETAP_THREAD_LOCK_SET , ETAP_TRACE_OFF , "th_lock_set" , 23}, ! 322: {ETAP_THREAD_NEW , ETAP_TRACE_OFF , "th_new" , 24}, ! 323: {ETAP_THREAD_PSET , ETAP_TRACE_OFF , "th_pset" , STATIC},/**/ ! 324: {ETAP_THREAD_PSET_ALL , ETAP_TRACE_OFF , "th_pset_all" , STATIC}, ! 325: {ETAP_THREAD_PSET_RUNQ , ETAP_TRACE_OFF , "th_pset_runq" , STATIC}, ! 326: {ETAP_THREAD_PSET_IDLE , ETAP_TRACE_OFF , "th_pset_idle" , STATIC}, ! 327: {ETAP_THREAD_PSET_QUANT , ETAP_TRACE_OFF , "th_pset_quant" , STATIC}, ! 328: {ETAP_THREAD_PROC , ETAP_TRACE_OFF , "th_proc" , STATIC}, ! 329: {ETAP_THREAD_PROC_RUNQ , ETAP_TRACE_OFF , "th_proc_runq" , STATIC}, ! 330: {ETAP_THREAD_REAPER , ETAP_TRACE_OFF , "th_reaper" , STATIC}, ! 331: {ETAP_THREAD_RPC , ETAP_TRACE_OFF , "th_rpc" , 25}, ! 332: {ETAP_THREAD_SEMA , ETAP_TRACE_OFF , "th_sema" , 26}, ! 333: {ETAP_THREAD_STACK , ETAP_TRACE_OFF , "th_stack" , STATIC}, ! 334: {ETAP_THREAD_STACK_USAGE , ETAP_TRACE_OFF , "th_stack_usage" , STATIC}, ! 335: {ETAP_THREAD_TASK_NEW , ETAP_TRACE_OFF , "th_task_new" , 27}, ! 336: {ETAP_THREAD_TASK_ITK , ETAP_TRACE_OFF , "th_task_itk" , 28}, ! 337: {ETAP_THREAD_ULOCK , ETAP_TRACE_OFF , "th_ulock" , 29}, ! 338: {ETAP_THREAD_WAIT , ETAP_TRACE_OFF , "th_wait" , STATIC}, ! 339: {ETAP_THREAD_WAKE , ETAP_TRACE_OFF , "th_wake" , 30}, ! 340: {ETAP_THREAD_ACT_LIST , ETAP_TRACE_OFF , "th_act_list" , 31}, ! 341: {ETAP_THREAD_TASK_SWAP , ETAP_TRACE_OFF , "th_task_swap" , 32}, ! 342: {ETAP_THREAD_TASK_SWAPOUT, ETAP_TRACE_OFF , "th_task_swapout" , 33}, ! 343: {ETAP_THREAD_SWAPPER , ETAP_TRACE_OFF , "th_swapper" , STATIC}, ! 344: ! 345: {ETAP_NET_IFQ , ETAP_TRACE_OFF , "net_ifq" , STATIC}, ! 346: {ETAP_NET_KMSG , ETAP_TRACE_OFF , "net_kmsg" , STATIC}, ! 347: {ETAP_NET_MBUF , ETAP_TRACE_OFF , "net_mbuf" , STATIC},/**/ ! 348: {ETAP_NET_POOL , ETAP_TRACE_OFF , "net_pool" , STATIC}, ! 349: {ETAP_NET_Q , ETAP_TRACE_OFF , "net_q" , STATIC}, ! 350: {ETAP_NET_QFREE , ETAP_TRACE_OFF , "net_qfree" , STATIC}, ! 351: {ETAP_NET_RCV , ETAP_TRACE_OFF , "net_rcv" , STATIC}, ! 352: {ETAP_NET_RCV_PLIST , ETAP_TRACE_OFF , "net_rcv_plist" , STATIC},/**/ ! 353: {ETAP_NET_THREAD , ETAP_TRACE_OFF , "net_thread" , STATIC}, ! 354: ! 355: {ETAP_NORMA_XMM , ETAP_TRACE_OFF , "norma_xmm" , STATIC}, ! 356: {ETAP_NORMA_XMMOBJ , ETAP_TRACE_OFF , "norma_xmmobj" , STATIC}, ! 357: {ETAP_NORMA_XMMCACHE , ETAP_TRACE_OFF , "norma_xmmcache" , STATIC}, ! 358: {ETAP_NORMA_MP , ETAP_TRACE_OFF , "norma_mp" , STATIC}, ! 359: {ETAP_NORMA_VOR , ETAP_TRACE_OFF , "norma_vor" , STATIC},/**/ ! 360: {ETAP_NORMA_TASK , ETAP_TRACE_OFF , "norma_task" , 38},/**/ ! 361: ! 362: {ETAP_DIPC_CLEANUP , ETAP_TRACE_OFF , "dipc_cleanup" , STATIC},/**/ ! 363: {ETAP_DIPC_MSG_PROG , ETAP_TRACE_OFF , "dipc_msgp_prog" , STATIC},/**/ ! 364: {ETAP_DIPC_PREP_QUEUE , ETAP_TRACE_OFF , "dipc_prep_queue" , STATIC},/**/ ! 365: {ETAP_DIPC_PREP_FILL , ETAP_TRACE_OFF , "dipc_prep_fill" , STATIC},/**/ ! 366: {ETAP_DIPC_MIGRATE , ETAP_TRACE_OFF , "dipc_migrate" , STATIC},/**/ ! 367: {ETAP_DIPC_DELIVER , ETAP_TRACE_OFF , "dipc_deliver" , STATIC},/**/ ! 368: {ETAP_DIPC_RECV_SYNC , ETAP_TRACE_OFF , "dipc_recv_sync" , STATIC},/**/ ! 369: {ETAP_DIPC_RPC , ETAP_TRACE_OFF , "dipc_rpc" , STATIC},/**/ ! 370: {ETAP_DIPC_MSG_REQ , ETAP_TRACE_OFF , "dipc_msg_req" , STATIC},/**/ ! 371: {ETAP_DIPC_MSG_ORDER , ETAP_TRACE_OFF , "dipc_msg_order" , STATIC},/**/ ! 372: {ETAP_DIPC_MSG_PREPQ , ETAP_TRACE_OFF , "dipc_msg_prepq" , STATIC},/**/ ! 373: {ETAP_DIPC_MSG_FREE , ETAP_TRACE_OFF , "dipc_msg_free" , STATIC},/**/ ! 374: {ETAP_DIPC_KMSG_AST , ETAP_TRACE_OFF , "dipc_kmsg_ast" , STATIC},/**/ ! 375: {ETAP_DIPC_TEST_LOCK , ETAP_TRACE_OFF , "dipc_test_lock" , STATIC},/**/ ! 376: {ETAP_DIPC_SPINLOCK , ETAP_TRACE_OFF , "dipc_spinlock" , STATIC},/**/ ! 377: {ETAP_DIPC_TRACE , ETAP_TRACE_OFF , "dipc_trace" , STATIC},/**/ ! 378: {ETAP_DIPC_REQ_CALLBACK , ETAP_TRACE_OFF , "dipc_req_clbck" , STATIC},/**/ ! 379: {ETAP_DIPC_PORT_NAME , ETAP_TRACE_OFF , "dipc_port_name" , STATIC},/**/ ! 380: {ETAP_DIPC_RESTART_PORT , ETAP_TRACE_OFF , "dipc_restart_port", STATIC},/**/ ! 381: {ETAP_DIPC_ZERO_PAGE , ETAP_TRACE_OFF , "dipc_zero_page" , STATIC},/**/ ! 382: {ETAP_DIPC_BLOCKED_NODE , ETAP_TRACE_OFF , "dipc_blocked_node", STATIC},/**/ ! 383: {ETAP_DIPC_TIMER , ETAP_TRACE_OFF , "dipc_timer" , STATIC},/**/ ! 384: {ETAP_DIPC_SPECIAL_PORT , ETAP_TRACE_OFF , "dipc_special_port", STATIC},/**/ ! 385: ! 386: {ETAP_KKT_TEST_WORK , ETAP_TRACE_OFF , "kkt_test_work" , STATIC},/**/ ! 387: {ETAP_KKT_TEST_MP , ETAP_TRACE_OFF , "kkt_work_mp" , STATIC},/**/ ! 388: {ETAP_KKT_NODE , ETAP_TRACE_OFF , "kkt_node" , STATIC},/**/ ! 389: {ETAP_KKT_CHANNEL_LIST , ETAP_TRACE_OFF , "kkt_channel_list" , STATIC},/**/ ! 390: {ETAP_KKT_CHANNEL , ETAP_TRACE_OFF , "kkt_channel" , STATIC},/**/ ! 391: {ETAP_KKT_HANDLE , ETAP_TRACE_OFF , "kkt_handle" , STATIC},/**/ ! 392: {ETAP_KKT_MAP , ETAP_TRACE_OFF , "kkt_map" , STATIC},/**/ ! 393: {ETAP_KKT_RESOURCE , ETAP_TRACE_OFF , "kkt_resource" , STATIC},/**/ ! 394: ! 395: {ETAP_XKERNEL_MASTER , ETAP_TRACE_OFF , "xkernel_master" , STATIC},/**/ ! 396: {ETAP_XKERNEL_EVENT , ETAP_TRACE_OFF , "xkernel_event" , STATIC},/**/ ! 397: {ETAP_XKERNEL_ETHINPUT , ETAP_TRACE_OFF , "xkernel_input" , STATIC},/**/ ! 398: ! 399: {ETAP_MISC_AST , ETAP_TRACE_OFF , "m_ast" , STATIC}, ! 400: {ETAP_MISC_CLOCK , ETAP_TRACE_OFF , "m_clock" , STATIC}, ! 401: {ETAP_MISC_EMULATE , ETAP_TRACE_OFF , "m_emulate" , 34}, ! 402: {ETAP_MISC_EVENT , ETAP_TRACE_OFF , "m_event" , STATIC}, ! 403: {ETAP_MISC_KDB , ETAP_TRACE_OFF , "m_kdb" , STATIC}, ! 404: {ETAP_MISC_PCB , ETAP_TRACE_OFF , "m_pcb" , 35}, ! 405: {ETAP_MISC_PRINTF , ETAP_TRACE_OFF , "m_printf" , STATIC}, ! 406: {ETAP_MISC_Q , ETAP_TRACE_OFF , "m_q" , STATIC}, ! 407: {ETAP_MISC_RPC_SUBSYS , ETAP_TRACE_OFF , "m_rpc_sub" , 36}, ! 408: {ETAP_MISC_RT_CLOCK , ETAP_TRACE_OFF , "m_rt_clock" , STATIC}, ! 409: {ETAP_MISC_SD_POOL , ETAP_TRACE_OFF , "m_sd_pool" , STATIC}, ! 410: {ETAP_MISC_TIMER , ETAP_TRACE_OFF , "m_timer" , STATIC}, ! 411: {ETAP_MISC_UTIME , ETAP_TRACE_OFF , "m_utime" , STATIC}, ! 412: {ETAP_MISC_XPR , ETAP_TRACE_OFF , "m_xpr" , STATIC}, ! 413: {ETAP_MISC_ZONE , ETAP_TRACE_OFF , "m_zone" , 37}, ! 414: {ETAP_MISC_ZONE_ALL , ETAP_TRACE_OFF , "m_zone_all" , STATIC}, ! 415: {ETAP_MISC_ZONE_GET , ETAP_TRACE_OFF , "m_zone_get" , STATIC}, ! 416: {ETAP_MISC_ZONE_PTABLE , ETAP_TRACE_OFF , "m_zone_ptable" , STATIC},/**/ ! 417: {ETAP_MISC_LEDGER , ETAP_TRACE_OFF , "m_ledger" , STATIC},/**/ ! 418: {ETAP_MISC_SCSIT_TGT , ETAP_TRACE_OFF , "m_scsit_tgt_lock" , STATIC},/**/ ! 419: {ETAP_MISC_SCSIT_SELF , ETAP_TRACE_OFF , "m_scsit_self_lock", STATIC},/**/ ! 420: {ETAP_MISC_SPL , ETAP_TRACE_OFF , "m_spl_lock" , STATIC},/**/ ! 421: {ETAP_MISC_MASTER , ETAP_TRACE_OFF , "m_master" , STATIC},/**/ ! 422: {ETAP_MISC_FLOAT , ETAP_TRACE_OFF , "m_float" , STATIC},/**/ ! 423: {ETAP_MISC_GROUP , ETAP_TRACE_OFF , "m_group" , STATIC},/**/ ! 424: {ETAP_MISC_FLIPC , ETAP_TRACE_OFF , "m_flipc" , STATIC},/**/ ! 425: {ETAP_MISC_MP_IO , ETAP_TRACE_OFF , "m_mp_io" , STATIC},/**/ ! 426: {ETAP_MISC_KERNEL_TEST , ETAP_TRACE_OFF , "m_kernel_test" , STATIC},/**/ ! 427: ! 428: {ETAP_NO_TRACE , ETAP_TRACE_OFF , "NEVER_TRACE" , STATIC}, ! 429: #endif /* ETAP_LOCK_TRACE */ ! 430: }; ! 431: ! 432: /* ! 433: * Variable initially pointing to the event table, then to its mappable ! 434: * copy. The cast is needed to discard the `const' qualifier; without it ! 435: * gcc issues a warning. ! 436: */ ! 437: event_table_t event_table = (event_table_t) event_table_init; ! 438: ! 439: /* ! 440: * Linked list of pointers into event_table_init[] so they can be switched ! 441: * into the mappable copy when it is made. ! 442: */ ! 443: struct event_table_chain *event_table_chain; ! 444: ! 445: /* ! 446: * max number of event types in the event table ! 447: */ ! 448: ! 449: int event_table_max = sizeof(event_table_init)/sizeof(struct event_table_entry); ! 450: ! 451: const struct subs_table_entry subs_table_init[] = ! 452: { ! 453: /*------------------------------------------* ! 454: * ETAP SUBSYSTEM TEXT NAME * ! 455: *------------------------------------------*/ ! 456: ! 457: #if ETAP_EVENT_MONITOR ! 458: {ETAP_SUBS_PROBE , "event_probes" }, ! 459: #endif /* ETAP_EVENT_MONITOR */ ! 460: ! 461: #if ETAP_LOCK_TRACE ! 462: {ETAP_SUBS_LOCK_DIPC , "lock_dipc" }, ! 463: {ETAP_SUBS_LOCK_IO , "lock_io" }, ! 464: {ETAP_SUBS_LOCK_IPC , "lock_ipc" }, ! 465: {ETAP_SUBS_LOCK_KKT , "lock_kkt" }, ! 466: {ETAP_SUBS_LOCK_MISC , "lock_misc" }, ! 467: {ETAP_SUBS_LOCK_NET , "lock_net" }, ! 468: {ETAP_SUBS_LOCK_NORMA , "lock_norma" }, ! 469: {ETAP_SUBS_LOCK_THREAD , "lock_thread" }, ! 470: {ETAP_SUBS_LOCK_VM , "lock_vm" }, ! 471: {ETAP_SUBS_LOCK_XKERNEL , "lock_xkernel" }, ! 472: #endif /* ETAP_LOCK_TRACE */ ! 473: }; ! 474: ! 475: /* ! 476: * Variable initially pointing to the subsystem table, then to its mappable ! 477: * copy. ! 478: */ ! 479: subs_table_t subs_table = (subs_table_t) subs_table_init; ! 480: ! 481: /* ! 482: * max number of subsystem types in the subsystem table ! 483: */ ! 484: ! 485: int subs_table_max = sizeof(subs_table_init)/sizeof(struct subs_table_entry); ! 486: ! 487: #if ETAP_MONITOR ! 488: #define MAX_NAME_SIZE 35 ! 489: ! 490: #define SYS_TABLE_MACH_TRAP 0 ! 491: #define SYS_TABLE_MACH_MESSAGE 1 ! 492: #define SYS_TABLE_UNIX_SYSCALL 2 ! 493: #define SYS_TABLE_INTERRUPT 3 ! 494: #define SYS_TABLE_EXCEPTION 4 ! 495: ! 496: ! 497: extern char *system_table_lookup (unsigned int table, ! 498: unsigned int number); ! 499: ! 500: ! 501: char *mach_trap_names[] = { ! 502: /* 0 */ "undefined", ! 503: /* 1 */ NULL, ! 504: /* 2 */ NULL, ! 505: /* 3 */ NULL, ! 506: /* 4 */ NULL, ! 507: /* 5 */ NULL, ! 508: /* 6 */ NULL, ! 509: /* 7 */ NULL, ! 510: /* 8 */ NULL, ! 511: /* 9 */ NULL, ! 512: /* 10 */ NULL, ! 513: /* 11 */ NULL, ! 514: /* 12 */ NULL, ! 515: /* 13 */ NULL, ! 516: /* 14 */ NULL, ! 517: /* 15 */ NULL, ! 518: /* 16 */ NULL, ! 519: /* 17 */ NULL, ! 520: /* 18 */ NULL, ! 521: /* 19 */ NULL, ! 522: /* 20 */ NULL, ! 523: /* 21 */ NULL, ! 524: /* 22 */ NULL, ! 525: /* 23 */ NULL, ! 526: /* 24 */ NULL, ! 527: /* 25 */ NULL, ! 528: /* 26 */ "mach_reply_port", ! 529: /* 27 */ "mach_thread_self", ! 530: /* 28 */ "mach_task_self", ! 531: /* 29 */ "mach_host_self", ! 532: /* 30 */ "vm_read_overwrite", ! 533: /* 31 */ "vm_write", ! 534: /* 32 */ "mach_msg_overwrite_trap", ! 535: /* 33 */ NULL, ! 536: /* 34 */ NULL, ! 537: #ifdef i386 ! 538: /* 35 */ "mach_rpc_trap", ! 539: /* 36 */ "mach_rpc_return_trap", ! 540: #else ! 541: /* 35 */ NULL, ! 542: /* 36 */ NULL, ! 543: #endif /* i386 */ ! 544: /* 37 */ NULL, ! 545: /* 38 */ NULL, ! 546: /* 39 */ NULL, ! 547: /* 40 */ NULL, ! 548: /* 41 */ "init_process", ! 549: /* 42 */ NULL, ! 550: /* 43 */ "map_fd", ! 551: /* 44 */ NULL, ! 552: /* 45 */ NULL, ! 553: /* 46 */ NULL, ! 554: /* 47 */ NULL, ! 555: /* 48 */ NULL, ! 556: /* 49 */ NULL, ! 557: /* 50 */ NULL, ! 558: /* 51 */ NULL, ! 559: /* 52 */ NULL, ! 560: /* 53 */ NULL, ! 561: /* 54 */ NULL, ! 562: /* 55 */ NULL, ! 563: /* 56 */ NULL, ! 564: /* 57 */ NULL, ! 565: /* 58 */ NULL, ! 566: /* 59 */ "swtch_pri", ! 567: /* 60 */ "swtch", ! 568: /* 61 */ "thread_switch", ! 569: /* 62 */ "clock_sleep_trap", ! 570: /* 63 */ NULL, ! 571: /* 64 */ NULL, ! 572: /* 65 */ NULL, ! 573: /* 66 */ NULL, ! 574: /* 67 */ NULL, ! 575: /* 68 */ NULL, ! 576: /* 69 */ NULL, ! 577: /* 70 */ NULL, ! 578: /* 71 */ NULL, ! 579: /* 72 */ NULL, ! 580: /* 73 */ NULL, ! 581: /* 74 */ NULL, ! 582: /* 75 */ NULL, ! 583: /* 76 */ NULL, ! 584: /* 77 */ NULL, ! 585: /* 78 */ NULL, ! 586: /* 79 */ NULL, ! 587: /* 80 */ NULL, ! 588: /* 81 */ NULL, ! 589: /* 82 */ NULL, ! 590: /* 83 */ NULL, ! 591: /* 84 */ NULL, ! 592: /* 85 */ NULL, ! 593: /* 86 */ NULL, ! 594: /* 87 */ NULL, ! 595: /* 88 */ NULL, ! 596: /* 89 */ NULL, ! 597: /* 90 */ NULL, ! 598: /* 91 */ NULL, ! 599: /* 92 */ NULL, ! 600: /* 93 */ NULL, ! 601: /* 94 */ NULL, ! 602: /* 95 */ NULL, ! 603: /* 96 */ NULL, ! 604: /* 97 */ NULL, ! 605: /* 98 */ NULL, ! 606: /* 99 */ NULL, ! 607: /* 100 */ NULL, ! 608: /* 101 */ NULL, ! 609: /* 102 */ NULL, ! 610: /* 103 */ NULL, ! 611: /* 104 */ NULL, ! 612: /* 105 */ NULL, ! 613: /* 106 */ NULL, ! 614: /* 107 */ NULL, ! 615: /* 108 */ NULL, ! 616: /* 109 */ NULL, ! 617: }; ! 618: #define N_MACH_TRAP_NAMES (sizeof mach_trap_names / sizeof mach_trap_names[0]) ! 619: #define mach_trap_name(nu) \ ! 620: (((nu) < N_MACH_TRAP_NAMES) ? mach_trap_names[nu] : NULL) ! 621: ! 622: struct table_entry { ! 623: char name[MAX_NAME_SIZE]; ! 624: u_int number; ! 625: }; ! 626: ! 627: /* ! 628: * Mach message table ! 629: * ! 630: * Note: Most mach system calls are actually implemented as messages. ! 631: */ ! 632: struct table_entry mach_message_table[] = { ! 633: subsystem_to_name_map_bootstrap, ! 634: subsystem_to_name_map_clock, ! 635: subsystem_to_name_map_clock_reply, ! 636: subsystem_to_name_map_default_pager_object, ! 637: subsystem_to_name_map_device, ! 638: subsystem_to_name_map_device_reply, ! 639: subsystem_to_name_map_device_request, ! 640: subsystem_to_name_map_exc, ! 641: /* subsystem_to_name_map_mach,*/ ! 642: subsystem_to_name_map_mach_debug, ! 643: /* subsystem_to_name_map_mach_host,*/ ! 644: subsystem_to_name_map_mach_norma, ! 645: subsystem_to_name_map_mach_port, ! 646: subsystem_to_name_map_memory_object, ! 647: subsystem_to_name_map_memory_object_default, ! 648: subsystem_to_name_map_notify, ! 649: subsystem_to_name_map_prof, ! 650: subsystem_to_name_map_sync ! 651: }; ! 652: ! 653: int mach_message_table_entries = sizeof(mach_message_table) / ! 654: sizeof(struct table_entry); ! 655: ! 656: ! 657: #endif ! 658: ! 659: /* ! 660: * ================================ ! 661: * Initialization routines for ETAP ! 662: * ================================ ! 663: */ ! 664: ! 665: /* ! 666: * ROUTINE: etap_init_phase1 [internal] ! 667: * ! 668: * FUNCTION: Event trace instrumentation initialization phase ! 669: * one of two. The static phase. The cumulative buffer ! 670: * is initialized. ! 671: * ! 672: * NOTES: The cumulative buffer is statically allocated and ! 673: * must be initialized before the first simple_lock_init() ! 674: * or lock_init() call is made. ! 675: * ! 676: * The first lock init call is made before dynamic allocation ! 677: * is available. Hence, phase one is executed before dynamic ! 678: * memory allocation is available. ! 679: * ! 680: */ ! 681: ! 682: void ! 683: etap_init_phase1(void) ! 684: { ! 685: #if ETAP_LOCK_ACCUMULATE || MACH_ASSERT ! 686: int x; ! 687: #if MACH_ASSERT ! 688: boolean_t out_of_order; ! 689: #endif /* MACH_ASSERT */ ! 690: #endif /* ETAP_LOCK_ACCUMULATE || MACH_ASSERT */ ! 691: ! 692: #if ETAP_LOCK_ACCUMULATE ! 693: /* ! 694: * Initialize Cumulative Buffer ! 695: * ! 696: * Note: The cumulative buffer is statically allocated. ! 697: * This static allocation is necessary since most ! 698: * of the lock_init calls are made before dynamic ! 699: * allocation routines are available. ! 700: */ ! 701: ! 702: /* ! 703: * Align cumulative buffer pointer to a page boundary ! 704: * (so it can be maped). ! 705: */ ! 706: ! 707: bzero(&cbuff_allocated[0], CBUFF_ALLOCATED_SIZE); ! 708: cbuff = (cumulative_buffer_t) round_page(&cbuff_allocated); ! 709: ! 710: simple_lock_init(&cbuff_lock, ETAP_NO_TRACE); ! 711: ! 712: /* ! 713: * Set the starting point for cumulative buffer entry ! 714: * reservations. ! 715: * ! 716: * This value must leave enough head room in the ! 717: * cumulative buffer to contain all dynamic events. ! 718: */ ! 719: ! 720: for (x=0; x < event_table_max; x++) ! 721: if (event_table[x].dynamic > cbuff->static_start) ! 722: cbuff->static_start = event_table[x].dynamic; ! 723: ! 724: cbuff->next = cbuff->static_start; ! 725: #endif /* ETAP_LOCK_ACCUMULATE */ ! 726: ! 727: /* ! 728: * Initialize the event table lock ! 729: */ ! 730: ! 731: simple_lock_init(&event_table_lock, ETAP_NO_TRACE); ! 732: ! 733: #if MACH_ASSERT ! 734: /* ! 735: * Check that events are in numerical order so we can do a binary ! 736: * search on them. Even better would be to make event numbers be ! 737: * simple contiguous indexes into event_table[], but that would ! 738: * break the coding of subsystems in the event number. ! 739: */ ! 740: out_of_order = FALSE; ! 741: for (x = 1; x < event_table_max; x++) { ! 742: if (event_table[x - 1].event > event_table[x].event) { ! 743: printf("events out of order: %s > %s\n", ! 744: event_table[x - 1].name, event_table[x].name); ! 745: out_of_order = TRUE; ! 746: } ! 747: } ! 748: if (out_of_order) ! 749: panic("etap_init_phase1"); ! 750: #endif /* MACH_ASSERT */ ! 751: } ! 752: ! 753: ! 754: /* ! 755: * ROUTINE: etap_init_phase2 [internal] ! 756: * ! 757: * FUNCTION: Event trace instrumentation initialization phase ! 758: * two of two. The dynamic phase. The monitored buffers ! 759: * are dynamically allocated and initialized. Cumulative ! 760: * dynamic entry locks are allocated and initialized. The ! 761: * start_data_pool is initialized. ! 762: * ! 763: * NOTES: Phase two is executed once dynamic memory allocation ! 764: * is available. ! 765: * ! 766: */ ! 767: ! 768: void ! 769: etap_init_phase2(void) ! 770: { ! 771: int size; ! 772: int x; ! 773: int ret; ! 774: vm_offset_t table_copy; ! 775: struct event_table_chain *chainp; ! 776: ! 777: /* ! 778: * Make mappable copies of the event_table and the subs_table. ! 779: * These tables were originally mapped as they appear in the ! 780: * kernel image, but that meant that other kernel variables could ! 781: * end up being mapped with them, which is ugly. It also didn't ! 782: * work on the HP/PA, where pages with physical address == virtual ! 783: * do not have real pmap entries allocated and therefore can't be ! 784: * mapped elsewhere. ! 785: */ ! 786: size = sizeof event_table_init + sizeof subs_table_init; ! 787: ret = kmem_alloc(kernel_map, &table_copy, size); ! 788: if (ret != KERN_SUCCESS) ! 789: panic("ETAP: error allocating table copies"); ! 790: event_table = (event_table_t) table_copy; ! 791: subs_table = (subs_table_t) (table_copy + sizeof event_table_init); ! 792: bcopy((char *) event_table_init, (char *) event_table, ! 793: sizeof event_table_init); ! 794: bcopy((char *) subs_table_init, (char *) subs_table, ! 795: sizeof subs_table_init); ! 796: ! 797: /* Switch pointers from the old event_table to the new. */ ! 798: for (chainp = event_table_chain; chainp != NULL; ! 799: chainp = chainp->event_table_link) { ! 800: x = chainp->event_tablep - event_table_init; ! 801: assert(x < event_table_max); ! 802: chainp->event_tablep = event_table + x; ! 803: } ! 804: ! 805: #if ETAP_LOCK_ACCUMULATE ! 806: ! 807: /* ! 808: * Because several dynamic locks can point to a single ! 809: * cumulative buffer entry, dynamic lock writes to the ! 810: * entry are synchronized. ! 811: * ! 812: * The spin locks are allocated here. ! 813: * ! 814: */ ! 815: #if MACH_LDEBUG ! 816: size = sizeof(simple_lock_t) * cbuff->static_start; ! 817: #else ! 818: /* ! 819: * Note: These locks are different from traditional spin locks. ! 820: * They are of type int instead of type simple_lock_t. ! 821: * We can reduce lock size this way, since no tracing will ! 822: * EVER be performed on these locks. ! 823: */ ! 824: size = sizeof(simple_lock_data_t) * cbuff->static_start; ! 825: #endif ! 826: ! 827: ret = kmem_alloc(kernel_map, (vm_offset_t *) &cbuff_locks, size); ! 828: ! 829: if (ret != KERN_SUCCESS) ! 830: panic("ETAP: error allocating cumulative write locks"); ! 831: ! 832: #if MACH_LDEBUG ! 833: for(x = 0; x < cbuff->static_start; ++x) { ! 834: simple_lock_init(&cbuff_locks[x], ETAP_NO_TRACE); ! 835: } ! 836: #else ! 837: bzero((const char *) cbuff_locks, size); ! 838: #endif ! 839: ! 840: #endif /* ETAP_LOCK_ACCUMULATE */ ! 841: ! 842: ! 843: #if ETAP_MONITOR ! 844: ! 845: /* ! 846: * monitor buffer allocation ! 847: */ ! 848: ! 849: size = ((mbuff_entries-1) * sizeof(struct mbuff_entry)) + ! 850: sizeof(struct monitor_buffer); ! 851: ! 852: for (x=0; x < NCPUS; x++) { ! 853: ret = kmem_alloc(kernel_map, ! 854: (vm_offset_t *) &mbuff[x], ! 855: size); ! 856: ! 857: if (ret != KERN_SUCCESS) ! 858: panic ("ETAP: error allocating monitor buffer\n"); ! 859: ! 860: /* zero fill buffer */ ! 861: bzero((char *) mbuff[x], size); ! 862: } ! 863: ! 864: #endif /* ETAP_MONITOR */ ! 865: ! 866: ! 867: #if ETAP_LOCK_TRACE ! 868: ! 869: /* ! 870: * Initialize the start_data_pool ! 871: */ ! 872: ! 873: init_start_data_pool(); ! 874: ! 875: #endif /* ETAP_LOCK_TRACE */ ! 876: } ! 877: ! 878: ! 879: #if ETAP_LOCK_ACCUMULATE ! 880: ! 881: /* ! 882: * ROUTINE: etap_cbuff_reserve [internal] ! 883: * ! 884: * FUNCTION: The cumulative buffer operation which returns a pointer ! 885: * to a free entry in the cumulative buffer. ! 886: * ! 887: * NOTES: Disables interrupts. ! 888: * ! 889: */ ! 890: ! 891: cbuff_entry_t ! 892: etap_cbuff_reserve(event_table_t etp) ! 893: { ! 894: cbuff_entry_t avail; ! 895: unsigned short de; ! 896: spl_t s; ! 897: ! 898: /* see if type pointer is initialized */ ! 899: if (etp == EVENT_TABLE_NULL || etp->event == ETAP_NO_TRACE) ! 900: return (CBUFF_ENTRY_NULL); ! 901: ! 902: /* check for DYNAMIC lock */ ! 903: if (de = etp->dynamic) { ! 904: if (de <= cbuff->static_start) ! 905: return (&cbuff->entry[de-1]); ! 906: else { ! 907: printf("ETAP: dynamic lock index error [%lu]\n", de); ! 908: return (CBUFF_ENTRY_NULL); ! 909: } ! 910: } ! 911: ! 912: cumulative_buffer_lock(s); ! 913: ! 914: /* if buffer is full, reservation requests fail */ ! 915: if (cbuff->next >= ETAP_CBUFF_ENTRIES) { ! 916: cumulative_buffer_unlock(s); ! 917: return (CBUFF_ENTRY_NULL); ! 918: } ! 919: ! 920: avail = &cbuff->entry[cbuff->next++]; ! 921: ! 922: cumulative_buffer_unlock(s); ! 923: ! 924: return (avail); ! 925: } ! 926: ! 927: #endif /* ETAP_LOCK_ACCUMULATE */ ! 928: ! 929: /* ! 930: * ROUTINE: etap_event_table_assign [internal] ! 931: * ! 932: * FUNCTION: Returns a pointer to the assigned event type table entry, ! 933: * using the event type as the index key. ! 934: * ! 935: */ ! 936: ! 937: event_table_t ! 938: etap_event_table_find(etap_event_t event) ! 939: { ! 940: int last_before, first_after, try; ! 941: ! 942: /* Binary search for the event number. last_before is the highest- ! 943: numbered element known to be <= the number we're looking for; ! 944: first_after is the lowest-numbered element known to be >. */ ! 945: last_before = 0; ! 946: first_after = event_table_max; ! 947: while (last_before < first_after) { ! 948: try = (last_before + first_after) >> 1; ! 949: if (event_table[try].event == event) ! 950: return (&event_table[try]); ! 951: else if (event_table[try].event < event) ! 952: last_before = try; ! 953: else ! 954: first_after = try; ! 955: } ! 956: return EVENT_TABLE_NULL; ! 957: } ! 958: ! 959: void ! 960: etap_event_table_assign(struct event_table_chain *chainp, etap_event_t event) ! 961: { ! 962: event_table_t event_tablep; ! 963: ! 964: event_tablep = etap_event_table_find(event); ! 965: if (event_tablep == EVENT_TABLE_NULL) ! 966: printf("\nETAP: event not found in event table: %x\n", event); ! 967: else { ! 968: if (event_table == event_table_init) { ! 969: chainp->event_table_link = event_table_chain; ! 970: event_table_chain = chainp; ! 971: } ! 972: chainp->event_tablep = event_tablep; ! 973: } ! 974: } ! 975: ! 976: #endif /* ETAP */ ! 977: ! 978: /* ! 979: * ! 980: * MESSAGE: etap_get_info [exported] ! 981: * ! 982: * FUNCTION: provides the server with ETAP buffer configurations. ! 983: * ! 984: */ ! 985: ! 986: kern_return_t ! 987: etap_get_info( ! 988: host_t host_priv, ! 989: int *et_entries, ! 990: int *st_entries, ! 991: vm_offset_t *et_offset, ! 992: vm_offset_t *st_offset, ! 993: int *cb_width, ! 994: int *mb_size, ! 995: int *mb_entries, ! 996: int *mb_cpus) ! 997: { ! 998: ! 999: #if ETAP ! 1000: *et_entries = event_table_max; ! 1001: *st_entries = subs_table_max; ! 1002: *et_offset = (vm_offset_t) ((char*) event_table - ! 1003: trunc_page((char*) event_table)); ! 1004: *st_offset = (vm_offset_t) ((char*) subs_table - ! 1005: trunc_page((char*) subs_table)); ! 1006: #else /* ETAP */ ! 1007: *et_entries = 0; ! 1008: *st_entries = 0; ! 1009: *et_offset = 0; ! 1010: *st_offset = 0; ! 1011: #endif /* ETAP */ ! 1012: ! 1013: #if ETAP_LOCK_ACCUMULATE ! 1014: *cb_width = cbuff_width; ! 1015: #else /* ETAP_LOCK_ACCUMULATE */ ! 1016: *cb_width = 0; ! 1017: #endif /* ETAP_LOCK_ACCUMULATE */ ! 1018: ! 1019: #if ETAP_MONITOR ! 1020: *mb_size = ((mbuff_entries-1) * sizeof(struct mbuff_entry)) + ! 1021: sizeof(struct monitor_buffer); ! 1022: *mb_entries = mbuff_entries; ! 1023: *mb_cpus = NCPUS; ! 1024: #else /* ETAP_MONITOR */ ! 1025: *mb_size = 0; ! 1026: *mb_entries = 0; ! 1027: *mb_cpus = 0; ! 1028: #endif /* ETAP_MONITOR */ ! 1029: ! 1030: return (KERN_SUCCESS); ! 1031: } ! 1032: ! 1033: /* ! 1034: * ROUTINE: etap_trace_event [exported] ! 1035: * ! 1036: * FUNCTION: The etap_trace_event system call is the user's interface to ! 1037: * the ETAP kernel instrumentation. ! 1038: * ! 1039: * This call allows the user to enable and disable tracing modes ! 1040: * on specific event types. The call also supports a reset option, ! 1041: * where the cumulative buffer data and all event type tracing ! 1042: * is reset to zero. When the reset option is used, a new ! 1043: * interval width can also be defined using the op parameter. ! 1044: * ! 1045: */ ! 1046: ! 1047: kern_return_t ! 1048: etap_trace_event ( ! 1049: unsigned short mode, ! 1050: unsigned short type, ! 1051: boolean_t enable, ! 1052: unsigned int nargs, ! 1053: unsigned short args[]) ! 1054: { ! 1055: #if ETAP ! 1056: event_table_t event_tablep; ! 1057: kern_return_t ret; ! 1058: int i, args_size; ! 1059: unsigned short status_mask; ! 1060: unsigned short *tmp_args; ! 1061: ! 1062: /* ! 1063: * Initialize operation ! 1064: */ ! 1065: ! 1066: if (mode == ETAP_RESET) { ! 1067: etap_trace_reset(nargs); ! 1068: return (KERN_SUCCESS); ! 1069: } ! 1070: ! 1071: status_mask = mode & type; ! 1072: ! 1073: /* ! 1074: * Copy args array from user space to kernel space ! 1075: */ ! 1076: ! 1077: args_size = nargs * sizeof *args; ! 1078: tmp_args = (unsigned short *) kalloc(args_size); ! 1079: ! 1080: if (tmp_args == NULL) ! 1081: return (KERN_NO_SPACE); ! 1082: ! 1083: if (copyin((const char *) args, (char *) tmp_args, args_size)) ! 1084: return (KERN_INVALID_ADDRESS); ! 1085: ! 1086: /* ! 1087: * Change appropriate status fields in the event table ! 1088: */ ! 1089: ! 1090: event_table_lock(); ! 1091: ! 1092: for (i = 0; i < nargs; i++) { ! 1093: if (tmp_args[i] != ETAP_NO_TRACE) { ! 1094: event_tablep = etap_event_table_find(tmp_args[i]); ! 1095: if (event_tablep == EVENT_TABLE_NULL) ! 1096: break; ! 1097: if (enable) ! 1098: event_tablep->status |= status_mask; ! 1099: else ! 1100: event_tablep->status &= ~status_mask; ! 1101: } ! 1102: } ! 1103: ! 1104: ret = (i < nargs) ? KERN_INVALID_ARGUMENT : KERN_SUCCESS; ! 1105: ! 1106: event_table_unlock(); ! 1107: ! 1108: kfree((vm_offset_t) tmp_args, args_size); ! 1109: ! 1110: return (ret); ! 1111: ! 1112: #else /* ETAP */ ! 1113: ! 1114: return (KERN_FAILURE); ! 1115: ! 1116: #endif /* ETAP */ ! 1117: } ! 1118: ! 1119: ! 1120: #if ETAP ! 1121: ! 1122: /* ! 1123: * ROUTINE: etap_trace_reset [internal] ! 1124: * ! 1125: * FUNCTION: Turns off all tracing and erases all the data accumulated ! 1126: * in the cumulative buffer. If the user defined a new ! 1127: * cumulative buffer interval width, it will be assigned here. ! 1128: * ! 1129: */ ! 1130: void ! 1131: etap_trace_reset(int new_interval) ! 1132: { ! 1133: event_table_t scan; ! 1134: int x; ! 1135: register s; ! 1136: ! 1137: /* ! 1138: * Wipe out trace fields in event table ! 1139: */ ! 1140: ! 1141: scan = event_table; ! 1142: ! 1143: event_table_lock(); ! 1144: ! 1145: for (x=0; x < event_table_max; x++) { ! 1146: scan->status = ETAP_TRACE_OFF; ! 1147: scan++; ! 1148: } ! 1149: ! 1150: event_table_unlock(); ! 1151: ! 1152: #if ETAP_LOCK_ACCUMULATE ! 1153: ! 1154: /* ! 1155: * Wipe out cumulative buffer statistical fields for all entries ! 1156: */ ! 1157: ! 1158: cumulative_buffer_lock(s); ! 1159: ! 1160: for (x=0; x < ETAP_CBUFF_ENTRIES; x++) { ! 1161: bzero ((char *) &cbuff->entry[x].hold, ! 1162: sizeof(struct cbuff_data)); ! 1163: bzero ((char *) &cbuff->entry[x].wait, ! 1164: sizeof(struct cbuff_data)); ! 1165: bzero ((char *) &cbuff->entry[x].hold_interval[0], ! 1166: sizeof(unsigned long) * ETAP_CBUFF_IBUCKETS); ! 1167: bzero ((char *) &cbuff->entry[x].wait_interval[0], ! 1168: sizeof(unsigned long) * ETAP_CBUFF_IBUCKETS); ! 1169: } ! 1170: ! 1171: /* ! 1172: * Assign interval width if the user defined a new one. ! 1173: */ ! 1174: ! 1175: if (new_interval != 0) ! 1176: cbuff_width = new_interval; ! 1177: ! 1178: cumulative_buffer_unlock(s); ! 1179: ! 1180: #endif /* ETAP_LOCK_ACCUMULATE */ ! 1181: } ! 1182: ! 1183: #endif /* ETAP */ ! 1184: ! 1185: /* ! 1186: * ROUTINE: etap_probe [exported] ! 1187: * ! 1188: * FUNCTION: The etap_probe system call serves as a user-level probe, ! 1189: * allowing user-level code to store event data into ! 1190: * the monitored buffer(s). ! 1191: */ ! 1192: ! 1193: kern_return_t ! 1194: etap_probe( ! 1195: unsigned short event_type, ! 1196: unsigned short event_id, ! 1197: unsigned int data_size, /* total size in bytes */ ! 1198: etap_data_t *data) ! 1199: { ! 1200: ! 1201: #if ETAP_MONITOR ! 1202: ! 1203: mbuff_entry_t mbuff_entryp; ! 1204: int cpu; ! 1205: int free; ! 1206: spl_t s; ! 1207: ! 1208: ! 1209: if (data_size > ETAP_DATA_SIZE) ! 1210: return (KERN_INVALID_ARGUMENT); ! 1211: ! 1212: if (event_table[event_type].status == ETAP_TRACE_OFF || ! 1213: event_table[event_type].event != event_type) ! 1214: return (KERN_NO_ACCESS); ! 1215: ! 1216: mp_disable_preemption(); ! 1217: cpu = cpu_number(); ! 1218: s = splhigh(); ! 1219: ! 1220: free = mbuff[cpu]->free; ! 1221: mbuff_entryp = &mbuff[cpu]->entry[free]; ! 1222: ! 1223: /* ! 1224: * Load monitor buffer entry ! 1225: */ ! 1226: ! 1227: ETAP_TIMESTAMP(mbuff_entryp->time); ! 1228: mbuff_entryp->event = event_id; ! 1229: mbuff_entryp->flags = USER_EVENT; ! 1230: mbuff_entryp->instance = (u_int) current_thread(); ! 1231: mbuff_entryp->pc = 0; ! 1232: ! 1233: if (data != ETAP_DATA_NULL) ! 1234: copyin((const char *) data, ! 1235: (char *) mbuff_entryp->data, ! 1236: data_size); ! 1237: ! 1238: mbuff[cpu]->free = (free+1) % mbuff_entries; ! 1239: ! 1240: if (mbuff[cpu]->free == 0) ! 1241: mbuff[cpu]->timestamp++; ! 1242: ! 1243: splx(s); ! 1244: mp_enable_preemption(); ! 1245: ! 1246: return (KERN_SUCCESS); ! 1247: ! 1248: #else /* ETAP_MONITOR */ ! 1249: return (KERN_FAILURE); ! 1250: #endif /* ETAP_MONITOR */ ! 1251: } ! 1252: ! 1253: /* ! 1254: * ROUTINE: etap_trace_thread [exported] ! 1255: * ! 1256: * FUNCTION: Toggles thread's ETAP trace status bit. ! 1257: */ ! 1258: ! 1259: kern_return_t ! 1260: etap_trace_thread( ! 1261: thread_act_t thr_act, ! 1262: boolean_t trace_status) ! 1263: { ! 1264: #if ETAP_EVENT_MONITOR ! 1265: ! 1266: thread_t thread; ! 1267: boolean_t old_status; ! 1268: etap_data_t probe_data; ! 1269: spl_t s; ! 1270: ! 1271: if (thr_act == THR_ACT_NULL) ! 1272: return (KERN_INVALID_ARGUMENT); ! 1273: ! 1274: thread = act_lock_thread(thr_act); ! 1275: ! 1276: if (thread == THREAD_NULL) { ! 1277: act_unlock_thread(thr_act); ! 1278: return (KERN_INVALID_ARGUMENT); ! 1279: } ! 1280: ! 1281: s = splsched(); ! 1282: thread_lock(thread); ! 1283: ! 1284: old_status = thread->etap_trace; ! 1285: thread->etap_trace = trace_status; ! 1286: ! 1287: ETAP_DATA_LOAD(probe_data[0],thr_act->task); ! 1288: ETAP_DATA_LOAD(probe_data[1],thr_act); ! 1289: ETAP_DATA_LOAD(probe_data[2],thread->sched_pri); ! 1290: ! 1291: thread_unlock(thread); ! 1292: splx(s); ! 1293: ! 1294: act_unlock_thread(thr_act); ! 1295: ! 1296: /* ! 1297: * Thread creation (ETAP_P_THREAD_LIFE: BEGIN) is ONLY recorded ! 1298: * here since a threads trace status is disabled by default. ! 1299: */ ! 1300: if (trace_status == TRUE && old_status == FALSE) { ! 1301: ETAP_PROBE_DATA(ETAP_P_THREAD_LIFE, ! 1302: EVENT_BEGIN, ! 1303: thread, ! 1304: &probe_data, ! 1305: ETAP_DATA_ENTRY*3); ! 1306: } ! 1307: ! 1308: /* ! 1309: * Thread termination is (falsely) recorded here if the trace ! 1310: * status has been disabled. This event is recorded to allow ! 1311: * users the option of tracing a portion of a threads execution. ! 1312: */ ! 1313: if (trace_status == FALSE && old_status == TRUE) { ! 1314: ETAP_PROBE_DATA(ETAP_P_THREAD_LIFE, ! 1315: EVENT_END, ! 1316: thread, ! 1317: &probe_data, ! 1318: ETAP_DATA_ENTRY*3); ! 1319: } ! 1320: ! 1321: return (KERN_SUCCESS); ! 1322: ! 1323: #else /* ETAP_EVENT_MONITOR */ ! 1324: return (KERN_FAILURE); ! 1325: #endif /* ETAP_EVENT_MONITOR */ ! 1326: } ! 1327: ! 1328: /* ! 1329: * ROUTINE: etap_mon_reconfig [exported] ! 1330: * ! 1331: * FUNCTION: Reallocates monitor buffers to hold specified number ! 1332: * of entries. ! 1333: * ! 1334: * NOTES: In multiprocessor (SMP) case, a lock needs to be added ! 1335: * here and in data collection macros to protect access ! 1336: * to mbuff_entries. ! 1337: */ ! 1338: kern_return_t ! 1339: etap_mon_reconfig( ! 1340: host_t host_priv, ! 1341: int nentries) ! 1342: { ! 1343: #if ETAP_EVENT_MONITOR ! 1344: struct monitor_buffer *nmbuff[NCPUS], *ombuff[NCPUS]; ! 1345: int s, size, osize, i, ret; ! 1346: ! 1347: if (nentries <= 0) /* must be at least 1 */ ! 1348: return (KERN_FAILURE); ! 1349: ! 1350: size = ((nentries-1) * sizeof(struct mbuff_entry)) + ! 1351: sizeof(struct monitor_buffer); ! 1352: ! 1353: for (i = 0; i < NCPUS; ++i) { ! 1354: ret = kmem_alloc(kernel_map, ! 1355: (vm_offset_t *)&nmbuff[i], ! 1356: size); ! 1357: if (ret != KERN_SUCCESS) { ! 1358: if (i > 0) { ! 1359: int j; ! 1360: ! 1361: for (j = 0; j < i; ++j) { ! 1362: kmem_free(kernel_map, ! 1363: (vm_offset_t)nmbuff[j], ! 1364: size); ! 1365: } ! 1366: } ! 1367: return (ret); ! 1368: } ! 1369: bzero((char *) nmbuff[i], size); ! 1370: } ! 1371: osize = ((mbuff_entries-1) * sizeof (struct mbuff_entry)) + ! 1372: sizeof (struct monitor_buffer); ! 1373: ! 1374: s = splhigh(); ! 1375: event_table_lock(); ! 1376: for (i = 0; i < NCPUS; ++i) { ! 1377: ombuff[i] = mbuff[i]; ! 1378: mbuff[i] = nmbuff[i]; ! 1379: } ! 1380: mbuff_entries = nentries; ! 1381: event_table_unlock(); ! 1382: splx(s); ! 1383: ! 1384: for (i = 0; i < NCPUS; ++i) { ! 1385: kmem_free(kernel_map, ! 1386: (vm_offset_t)ombuff[i], ! 1387: osize); ! 1388: } ! 1389: return (KERN_SUCCESS); ! 1390: #else ! 1391: return (KERN_FAILURE); ! 1392: #endif /* ETAP_MONITOR */ ! 1393: } ! 1394: ! 1395: /* ! 1396: * ROUTINE: etap_new_probe [exported] ! 1397: * ! 1398: * FUNCTION: Reallocates monitor probe table, adding a new entry ! 1399: * ! 1400: */ ! 1401: kern_return_t ! 1402: etap_new_probe( ! 1403: host_t host_priv, ! 1404: vm_address_t name, ! 1405: vm_size_t namlen, ! 1406: boolean_t trace_on, ! 1407: vm_address_t id) ! 1408: { ! 1409: #if ETAP_EVENT_MONITOR ! 1410: event_table_t newtable, oldtable; ! 1411: unsigned short i, nid; ! 1412: int s; ! 1413: vm_size_t newsize = (event_table_max + 1) * ! 1414: sizeof (struct event_table_entry); ! 1415: boolean_t duplicate_name = FALSE; ! 1416: kern_return_t ret; ! 1417: ! 1418: if (namlen > EVENT_NAME_LENGTH - 1) ! 1419: return (KERN_INVALID_ARGUMENT); ! 1420: ! 1421: if ((ret = kmem_alloc(kernel_map, (vm_address_t *)&newtable, ! 1422: newsize)) != KERN_SUCCESS) ! 1423: return (ret); ! 1424: ! 1425: bcopy((const char *)event_table, (char *)newtable, event_table_max * ! 1426: sizeof (struct event_table_entry)); ! 1427: ! 1428: if (copyin((const char *)name, ! 1429: (char *)&newtable[event_table_max].name, namlen)) ! 1430: return (KERN_INVALID_ADDRESS); ! 1431: ! 1432: newtable[event_table_max].name[EVENT_NAME_LENGTH - 1] = '\0'; ! 1433: newtable[event_table_max].status = trace_on; ! 1434: newtable[event_table_max].dynamic = 0; ! 1435: ! 1436: for (nid = i = 0; i < event_table_max; ++i) { ! 1437: if (strcmp((char *)newtable[event_table_max].name, ! 1438: newtable[i].name) == 0) { ! 1439: duplicate_name = TRUE; ! 1440: printf("duplicate name\n"); ! 1441: } ! 1442: nid = max(nid, newtable[i].event); ! 1443: } ! 1444: ++nid; ! 1445: ! 1446: if (nid >= ETAP_NO_TRACE || duplicate_name == TRUE) { ! 1447: kmem_free(kernel_map, (vm_address_t)newtable, newsize); ! 1448: if (nid >= ETAP_NO_TRACE) { ! 1449: printf("KERN_RESOURCE_SHORTAGE\n"); ! 1450: return (KERN_RESOURCE_SHORTAGE); ! 1451: } ! 1452: else { ! 1453: printf("KERN_NAME_EXISTS\n"); ! 1454: return (KERN_NAME_EXISTS); ! 1455: } ! 1456: } ! 1457: ! 1458: newtable[event_table_max].event = nid; ! 1459: ! 1460: s = splhigh(); ! 1461: event_table_lock(); ! 1462: oldtable = event_table; ! 1463: event_table = newtable; ! 1464: ++event_table_max; ! 1465: event_table_unlock(); ! 1466: splx(s); ! 1467: ! 1468: if (oldtable != event_table_init) ! 1469: kmem_free(kernel_map, (vm_address_t)oldtable, ! 1470: (event_table_max - 1) * ! 1471: sizeof (struct event_table_entry)); ! 1472: ! 1473: *(unsigned short *)id = nid; ! 1474: ! 1475: return (KERN_SUCCESS); ! 1476: #else ! 1477: return (KERN_FAILURE); ! 1478: #endif /* ETAP_EVENT_MONITOR */ ! 1479: ! 1480: } ! 1481: /* ! 1482: * ETAP trap probe hooks ! 1483: */ ! 1484: ! 1485: void ! 1486: etap_interrupt_probe(int interrupt, int flag_setting) ! 1487: { ! 1488: u_short flag; ! 1489: ! 1490: if (flag_setting == 1) ! 1491: flag = EVENT_BEGIN; ! 1492: else ! 1493: flag = EVENT_END; ! 1494: ! 1495: ETAP_PROBE_DATA_COND(ETAP_P_INTERRUPT, ! 1496: flag, ! 1497: current_thread(), ! 1498: &interrupt, ! 1499: sizeof(int), ! 1500: 1); ! 1501: } ! 1502: ! 1503: void ! 1504: etap_machcall_probe1(int syscall) ! 1505: { ! 1506: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 1507: EVENT_BEGIN | SYSCALL_TRAP, ! 1508: current_thread(), ! 1509: &syscall, ! 1510: sizeof(int)); ! 1511: } ! 1512: ! 1513: void ! 1514: etap_machcall_probe2(void) ! 1515: { ! 1516: ETAP_PROBE_DATA(ETAP_P_SYSCALL_MACH, ! 1517: EVENT_END | SYSCALL_TRAP, ! 1518: current_thread(), ! 1519: 0, ! 1520: 0); ! 1521: } ! 1522: ! 1523: static void print_user_event(mbuff_entry_t); ! 1524: static void print_kernel_event(mbuff_entry_t, boolean_t); ! 1525: static void print_lock_event(mbuff_entry_t, const char *); ! 1526: ! 1527: #if MACH_KDB ! 1528: void db_show_etap_log(db_expr_t, boolean_t, db_expr_t, char *); ! 1529: /* ! 1530: * ! 1531: * ROUTINE: etap_print [internal] ! 1532: * ! 1533: * FUNCTION: print each mbuff table (for use in debugger) ! 1534: * ! 1535: */ ! 1536: void ! 1537: db_show_etap_log( ! 1538: db_expr_t addr, ! 1539: boolean_t have_addr, ! 1540: db_expr_t count, ! 1541: char * modif) ! 1542: { ! 1543: #if ETAP_MONITOR ! 1544: int cpu = cpu_number(), last, i, first, step, end, restart; ! 1545: boolean_t show_data = FALSE; ! 1546: ! 1547: last = (mbuff[cpu]->free - 1) % mbuff_entries; ! 1548: ! 1549: if(db_option(modif, 'r')) { ! 1550: first = last; ! 1551: step = -1; ! 1552: end = -1; ! 1553: restart = mbuff_entries - 1; ! 1554: } else { ! 1555: first = last + 1; ! 1556: step = 1; ! 1557: end = mbuff_entries; ! 1558: restart = 0; ! 1559: } ! 1560: ! 1561: if(db_option(modif, 'd')) ! 1562: show_data = TRUE; ! 1563: ! 1564: for(i = first; i != end; i += step) { ! 1565: if (mbuff[cpu]->entry[i].flags & USER_EVENT) ! 1566: print_user_event(&mbuff[cpu]->entry[i]); ! 1567: else ! 1568: print_kernel_event(&mbuff[cpu]->entry[i], show_data); ! 1569: } ! 1570: for(i = restart; i != first; i += step) { ! 1571: if (mbuff[cpu]->entry[i].flags & USER_EVENT) ! 1572: print_user_event(&mbuff[cpu]->entry[i]); ! 1573: else ! 1574: print_kernel_event(&mbuff[cpu]->entry[i], show_data); ! 1575: } ! 1576: #else ! 1577: printf("ETAP event monitor not configured\n"); ! 1578: #endif /* ETAP_MONITOR */ ! 1579: } ! 1580: ! 1581: #if ETAP_MONITOR ! 1582: static ! 1583: void ! 1584: print_user_event(mbuff_entry_t record) ! 1585: { ! 1586: char *s, buf[256]; ! 1587: ! 1588: db_printf("%x: %x%08x: ", record->instance, record->time.tv_sec, ! 1589: record->time.tv_nsec); ! 1590: switch (record->pc) ! 1591: { ! 1592: case ETAP_P_USER_EVENT0: s = "0"; break; ! 1593: case ETAP_P_USER_EVENT1: s = "1"; break; ! 1594: case ETAP_P_USER_EVENT2: s = "2"; break; ! 1595: case ETAP_P_USER_EVENT3: s = "3"; break; ! 1596: case ETAP_P_USER_EVENT4: s = "4"; break; ! 1597: case ETAP_P_USER_EVENT5: s = "5"; break; ! 1598: case ETAP_P_USER_EVENT6: s = "6"; break; ! 1599: case ETAP_P_USER_EVENT7: s = "7"; break; ! 1600: case ETAP_P_USER_EVENT8: s = "8"; break; ! 1601: case ETAP_P_USER_EVENT9: s = "9"; break; ! 1602: case ETAP_P_USER_EVENT10: s = "10"; break; ! 1603: case ETAP_P_USER_EVENT11: s = "11"; break; ! 1604: case ETAP_P_USER_EVENT12: s = "12"; break; ! 1605: case ETAP_P_USER_EVENT13: s = "13"; break; ! 1606: case ETAP_P_USER_EVENT14: s = "14"; break; ! 1607: case ETAP_P_USER_EVENT15: s = "15"; break; ! 1608: case ETAP_P_USER_EVENT16: s = "16"; break; ! 1609: case ETAP_P_USER_EVENT17: s = "17"; break; ! 1610: case ETAP_P_USER_EVENT18: s = "18"; break; ! 1611: case ETAP_P_USER_EVENT19: s = "19"; break; ! 1612: case ETAP_P_USER_EVENT20: s = "20"; break; ! 1613: case ETAP_P_USER_EVENT21: s = "21"; break; ! 1614: case ETAP_P_USER_EVENT22: s = "22"; break; ! 1615: case ETAP_P_USER_EVENT23: s = "23"; break; ! 1616: case ETAP_P_USER_EVENT24: s = "24"; break; ! 1617: case ETAP_P_USER_EVENT25: s = "25"; break; ! 1618: case ETAP_P_USER_EVENT26: s = "26"; break; ! 1619: case ETAP_P_USER_EVENT27: s = "27"; break; ! 1620: case ETAP_P_USER_EVENT28: s = "28"; break; ! 1621: case ETAP_P_USER_EVENT29: s = "29"; break; ! 1622: case ETAP_P_USER_EVENT30: s = "30"; break; ! 1623: case ETAP_P_USER_EVENT31: s = "31"; break; ! 1624: default: ! 1625: sprintf(buf, "dynamic %x", record->pc); ! 1626: s = buf; ! 1627: break; ! 1628: } ! 1629: ! 1630: db_printf("user probe %s: [%x] data = %x %x %x %x\n", ! 1631: s, ! 1632: record->event, ! 1633: record->data[0], ! 1634: record->data[1], ! 1635: record->data[2], ! 1636: record->data[3]); ! 1637: } ! 1638: ! 1639: static ! 1640: void ! 1641: print_kernel_event(mbuff_entry_t record, boolean_t data) ! 1642: { ! 1643: char *text_name; ! 1644: int i; ! 1645: ! 1646: /* assume zero event means that record was never written to */ ! 1647: if(record->event == 0) ! 1648: return; ! 1649: ! 1650: db_printf("%x: %x%08x: ", record->instance, record->time.tv_sec, ! 1651: record->time.tv_nsec); ! 1652: ! 1653: switch (record->event) { ! 1654: ! 1655: case ETAP_P_THREAD_LIFE : ! 1656: if (record->flags & EVENT_BEGIN) ! 1657: db_printf("thread created [T:%x A:%x] P:%d\n", ! 1658: record->data[0], ! 1659: record->data[1], ! 1660: record->data[2]); ! 1661: else ! 1662: db_printf("thread terminated [T:%x A:%x] P:%d\n", ! 1663: record->data[0], ! 1664: record->data[1], ! 1665: record->data[2]); ! 1666: break; ! 1667: ! 1668: case ETAP_P_SYSCALL_MACH : ! 1669: if (record->flags & SYSCALL_TRAP) ! 1670: text_name = system_table_lookup(SYS_TABLE_MACH_TRAP, ! 1671: record->data[0]); ! 1672: else ! 1673: text_name = system_table_lookup(SYS_TABLE_MACH_MESSAGE, ! 1674: record->data[0]); ! 1675: ! 1676: if (record->flags & EVENT_BEGIN) ! 1677: db_printf("mach enter: %s [%x]\n", ! 1678: text_name, ! 1679: record->data[0]); ! 1680: else ! 1681: db_printf("mach exit :\n"); ! 1682: break; ! 1683: ! 1684: case ETAP_P_SYSCALL_UNIX : ! 1685: text_name = system_table_lookup(SYS_TABLE_UNIX_SYSCALL, ! 1686: record->data[0]); ! 1687: ! 1688: if (record->flags & EVENT_BEGIN) ! 1689: db_printf("unix enter: %s\n", text_name); ! 1690: else ! 1691: db_printf("unix exit : %s\n", text_name); ! 1692: break; ! 1693: ! 1694: case ETAP_P_THREAD_CTX : ! 1695: if (record->flags & EVENT_END) ! 1696: db_printf("context switch to %x ", ! 1697: record->data[0]); ! 1698: else /* EVENT_BEGIN */ ! 1699: db_printf("context switch from %x ", ! 1700: record->data[0]); ! 1701: ! 1702: switch (record->data[1]) { ! 1703: case BLOCKED_ON_SEMAPHORE : ! 1704: db_printf("R: semaphore\n"); break; ! 1705: case BLOCKED_ON_LOCK : ! 1706: db_printf("R: lock\n"); break; ! 1707: case BLOCKED_ON_MUTEX_LOCK : ! 1708: db_printf("R: mutex lock\n"); break; ! 1709: case BLOCKED_ON_COMPLEX_LOCK : ! 1710: db_printf("R: complex lock\n"); break; ! 1711: case BLOCKED_ON_PORT_RCV : ! 1712: db_printf("R: port receive\n"); break; ! 1713: case BLOCKED_ON_REAPER_DONE : ! 1714: db_printf("R: reaper thread done\n"); break; ! 1715: case BLOCKED_ON_IDLE_DONE : ! 1716: db_printf("R: idle thread done\n"); break; ! 1717: case BLOCKED_ON_TERMINATION : ! 1718: db_printf("R: termination\n"); break; ! 1719: default : ! 1720: if (record->data[2]) ! 1721: db_printf("R: ast %x\n", record->data[2]); ! 1722: else ! 1723: db_printf("R: undefined block\n"); ! 1724: }; ! 1725: break; ! 1726: ! 1727: case ETAP_P_INTERRUPT : ! 1728: if (record->flags & EVENT_BEGIN) { ! 1729: text_name = system_table_lookup(SYS_TABLE_INTERRUPT, ! 1730: record->data[0]); ! 1731: db_printf("intr enter: %s\n", text_name); ! 1732: } else ! 1733: db_printf("intr exit\n"); ! 1734: break; ! 1735: ! 1736: case ETAP_P_ACT_ABORT : ! 1737: db_printf("activation abort [A %x : S %x]\n", ! 1738: record->data[1], ! 1739: ! 1740: record->data[0]); ! 1741: break; ! 1742: ! 1743: case ETAP_P_PRIORITY : ! 1744: db_printf("priority changed for %x N:%d O:%d\n", ! 1745: record->data[0], ! 1746: record->data[1], ! 1747: record->data[2]); ! 1748: break; ! 1749: ! 1750: case ETAP_P_EXCEPTION : ! 1751: text_name = system_table_lookup(SYS_TABLE_EXCEPTION, ! 1752: record->data[0]); ! 1753: db_printf("exception: %s\n", text_name); ! 1754: break; ! 1755: ! 1756: case ETAP_P_DEPRESSION : ! 1757: if (record->flags & EVENT_BEGIN) ! 1758: db_printf("priority depressed\n"); ! 1759: else { ! 1760: if (record->data[0] == 0) ! 1761: db_printf("priority undepressed : timed out\n"); ! 1762: else ! 1763: db_printf("priority undepressed : self inflicted\n"); ! 1764: } ! 1765: break; ! 1766: ! 1767: case ETAP_P_MISC : ! 1768: db_printf("flags: %x data: %x %x %x %x\n", record->flags, ! 1769: record->data[0], record->data[1], record->data[2], ! 1770: record->data[3]); ! 1771: break; ! 1772: ! 1773: case ETAP_P_DETAP : ! 1774: printf("flags: %x rtc: %x %09x dtime: %x %09x\n", ! 1775: record->flags, record->data[0], record->data[1], ! 1776: record->data[2], record->data[3]); ! 1777: break; ! 1778: ! 1779: default: ! 1780: for(i = 0; event_table_init[i].event != ETAP_NO_TRACE; ++i) ! 1781: if(record->event == event_table_init[i].event) { ! 1782: print_lock_event(record, event_table_init[i].name); ! 1783: return; ! 1784: } ! 1785: db_printf("Unknown event: %d\n", record->event); ! 1786: break; ! 1787: } ! 1788: if(data) ! 1789: db_printf(" Data: %08x %08x %08x %08x\n", record->data[0], ! 1790: record->data[1], record->data[2], record->data[3]); ! 1791: } ! 1792: ! 1793: void print_lock_event(mbuff_entry_t record, const char *name) ! 1794: { ! 1795: char *sym1, *sym2; ! 1796: db_addr_t offset1, offset2; ! 1797: ! 1798: db_find_sym_and_offset(record->data[0], &sym1, &offset1); ! 1799: ! 1800: db_printf("%15s", name); ! 1801: if (record->flags & SPIN_LOCK) ! 1802: printf(" spin "); ! 1803: else if (record->flags & READ_LOCK) ! 1804: printf(" read "); ! 1805: else if (record->flags & WRITE_LOCK) ! 1806: printf(" write "); ! 1807: else ! 1808: printf(" undef "); ! 1809: ! 1810: if (record->flags & ETAP_CONTENTION) { ! 1811: db_printf("wait lock %s+%x\n", ! 1812: sym1, offset1); ! 1813: } ! 1814: else if (record->flags & ETAP_DURATION) { ! 1815: db_find_sym_and_offset(record->data[1], &sym2, &offset2); ! 1816: db_printf("lock %x+%x unlock %x+%x\n", ! 1817: sym1, offset1, sym2, offset2); ! 1818: } else { ! 1819: db_printf("illegal op: neither HOLD or WAIT are specified\n"); ! 1820: } ! 1821: ! 1822: } ! 1823: ! 1824: char * ! 1825: system_table_lookup(unsigned int table, unsigned int number) ! 1826: { ! 1827: int x; ! 1828: char *name = NULL; ! 1829: unsigned int offset; ! 1830: ! 1831: switch (table) { ! 1832: case SYS_TABLE_MACH_TRAP: ! 1833: name = mach_trap_name(number >> 4); ! 1834: break; ! 1835: case SYS_TABLE_MACH_MESSAGE: ! 1836: for (x=0; x < mach_message_table_entries; x++) { ! 1837: if (mach_message_table[x].number == number) { ! 1838: name = mach_message_table[x].name; ! 1839: break; ! 1840: } ! 1841: } ! 1842: break; ! 1843: case SYS_TABLE_UNIX_SYSCALL: ! 1844: number = -number; ! 1845: name = syscall_name(number); ! 1846: break; ! 1847: case SYS_TABLE_INTERRUPT: ! 1848: db_find_sym_and_offset((int)ivect[number], &name, &offset); ! 1849: break; ! 1850: case SYS_TABLE_EXCEPTION: ! 1851: name = exception_name(number); ! 1852: break; ! 1853: } ! 1854: return (name != NULL) ? name : "undefined"; ! 1855: } ! 1856: ! 1857: #endif /* MACH_KDB */ ! 1858: #endif /* ETAP_MONITOR */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.