Annotation of XNU/osfmk/kern/etap.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.