Home | History | Annotate | Line # | Download | only in kern
kern_history.c revision 1.8
      1 /*	$NetBSD: kern_history.c,v 1.8 2016/12/26 23:49:53 pgoyette Exp $	 */
      2 
      3 /*
      4  * Copyright (c) 1997 Charles D. Cranor and Washington University.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  *
     27  * from: NetBSD: uvm_stat.c,v 1.36 2011/02/02 15:13:34 chuck Exp
     28  * from: Id: uvm_stat.c,v 1.1.2.3 1997/12/19 15:01:00 mrg Exp
     29  */
     30 
     31 /*
     32  * subr_kernhist.c
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: kern_history.c,v 1.8 2016/12/26 23:49:53 pgoyette Exp $");
     37 
     38 #include "opt_ddb.h"
     39 #include "opt_kernhist.h"
     40 #include "opt_syscall_debug.h"
     41 #include "opt_usb.h"
     42 #include "opt_uvmhist.h"
     43 #include "opt_biohist.h"
     44 
     45 #include <sys/param.h>
     46 #include <sys/systm.h>
     47 #include <sys/cpu.h>
     48 #include <sys/kernhist.h>
     49 
     50 #ifdef UVMHIST
     51 #include <uvm/uvm.h>
     52 #endif
     53 
     54 #ifdef USB_DEBUG
     55 #include <dev/usb/usbhist.h>
     56 #endif
     57 
     58 #ifdef BIOHIST
     59 #include <sys/biohist.h>
     60 #endif
     61 
     62 #ifdef SYSCALL_DEBUG
     63 KERNHIST_DECL(scdebughist);
     64 #endif
     65 
     66 /*
     67  * globals
     68  */
     69 
     70 struct kern_history_head kern_histories;
     71 
     72 int kernhist_print_enabled = 1;
     73 
     74 #ifdef DDB
     75 
     76 /*
     77  * prototypes
     78  */
     79 
     80 void kernhist_dump(struct kern_history *,
     81     void (*)(const char *, ...) __printflike(1, 2));
     82 void kernhist_dumpmask(u_int32_t);
     83 static void kernhist_dump_histories(struct kern_history *[],
     84     void (*)(const char *, ...) __printflike(1, 2));
     85 
     86 
     87 /*
     88  * call this from ddb
     89  *
     90  * expects the system to be quiesced, no locking
     91  */
     92 void
     93 kernhist_dump(struct kern_history *l, void (*pr)(const char *, ...))
     94 {
     95 	int lcv;
     96 
     97 	lcv = l->f;
     98 	do {
     99 		if (l->e[lcv].fmt)
    100 			kernhist_entry_print(&l->e[lcv], pr);
    101 		lcv = (lcv + 1) % l->n;
    102 	} while (lcv != l->f);
    103 }
    104 
    105 /*
    106  * print a merged list of kern_history structures
    107  */
    108 static void
    109 kernhist_dump_histories(struct kern_history *hists[], void (*pr)(const char *, ...))
    110 {
    111 	struct timeval  tv;
    112 	int	cur[MAXHISTS];
    113 	int	lcv, hi;
    114 
    115 	/* find the first of each list */
    116 	for (lcv = 0; hists[lcv]; lcv++)
    117 		 cur[lcv] = hists[lcv]->f;
    118 
    119 	/*
    120 	 * here we loop "forever", finding the next earliest
    121 	 * history entry and printing it.  cur[X] is the current
    122 	 * entry to test for the history in hists[X].  if it is
    123 	 * -1, then this history is finished.
    124 	 */
    125 	for (;;) {
    126 		hi = -1;
    127 		tv.tv_sec = tv.tv_usec = 0;
    128 
    129 		/* loop over each history */
    130 		for (lcv = 0; hists[lcv]; lcv++) {
    131 restart:
    132 			if (cur[lcv] == -1)
    133 				continue;
    134 			if (!hists[lcv]->e)
    135 				continue;
    136 
    137 			/*
    138 			 * if the format is empty, go to the next entry
    139 			 * and retry.
    140 			 */
    141 			if (hists[lcv]->e[cur[lcv]].fmt == NULL) {
    142 				cur[lcv] = (cur[lcv] + 1) % (hists[lcv]->n);
    143 				if (cur[lcv] == hists[lcv]->f)
    144 					cur[lcv] = -1;
    145 				goto restart;
    146 			}
    147 
    148 			/*
    149 			 * if the time hasn't been set yet, or this entry is
    150 			 * earlier than the current tv, set the time and history
    151 			 * index.
    152 			 */
    153 			if (tv.tv_sec == 0 ||
    154 			    timercmp(&hists[lcv]->e[cur[lcv]].tv, &tv, <)) {
    155 				tv = hists[lcv]->e[cur[lcv]].tv;
    156 				hi = lcv;
    157 			}
    158 		}
    159 
    160 		/* if we didn't find any entries, we must be done */
    161 		if (hi == -1)
    162 			break;
    163 
    164 		/* print and move to the next entry */
    165 		kernhist_entry_print(&hists[hi]->e[cur[hi]], pr);
    166 		cur[hi] = (cur[hi] + 1) % (hists[hi]->n);
    167 		if (cur[hi] == hists[hi]->f)
    168 			cur[hi] = -1;
    169 	}
    170 }
    171 
    172 /*
    173  * call this from ddb.  `bitmask' is from <sys/kernhist.h>.  it
    174  * merges the named histories.
    175  *
    176  * expects the system to be quiesced, no locking
    177  */
    178 void
    179 kernhist_dumpmask(u_int32_t bitmask)	/* XXX only support 32 hists */
    180 {
    181 	struct kern_history *hists[MAXHISTS + 1];
    182 	int i = 0;
    183 
    184 #ifdef UVMHIST
    185 	if ((bitmask & KERNHIST_UVMMAPHIST) || bitmask == 0)
    186 		hists[i++] = &maphist;
    187 
    188 	if ((bitmask & KERNHIST_UVMPDHIST) || bitmask == 0)
    189 		hists[i++] = &pdhist;
    190 
    191 	if ((bitmask & KERNHIST_UVMUBCHIST) || bitmask == 0)
    192 		hists[i++] = &ubchist;
    193 
    194 	if ((bitmask & KERNHIST_UVMLOANHIST) || bitmask == 0)
    195 		hists[i++] = &loanhist;
    196 #endif
    197 
    198 #ifdef USB_DEBUG
    199 	if ((bitmask & KERNHIST_USBHIST) || bitmask == 0)
    200 		hists[i++] = &usbhist;
    201 #endif
    202 
    203 #ifdef SYSCALL_DEBUG
    204 	if ((bitmask & KERNHIST_SCDEBUGHIST) || bitmask == 0)
    205 		hists[i++] = &scdebughist;
    206 #endif
    207 
    208 #ifdef BIOHIST
    209 	if ((bitmask & KERNHIST_BIOHIST) || bitmask == 0)
    210 		hists[i++] = &biohist;
    211 #endif
    212 
    213 	hists[i] = NULL;
    214 
    215 	kernhist_dump_histories(hists, printf);
    216 }
    217 
    218 /*
    219  * kernhist_print: ddb hook to print kern history
    220  */
    221 void
    222 kernhist_print(void *addr, void (*pr)(const char *, ...) __printflike(1,2))
    223 {
    224 	struct kern_history *h;
    225 
    226 	LIST_FOREACH(h, &kern_histories, list) {
    227 		if (h == addr)
    228 			break;
    229 	}
    230 
    231 	if (h == NULL) {
    232 		struct kern_history *hists[MAXHISTS + 1];
    233 		int i = 0;
    234 #ifdef UVMHIST
    235 		hists[i++] = &maphist;
    236 		hists[i++] = &pdhist;
    237 		hists[i++] = &ubchist;
    238 		hists[i++] = &loanhist;
    239 #endif
    240 #ifdef USB_DEBUG
    241 		hists[i++] = &usbhist;
    242 #endif
    243 
    244 #ifdef SYSCALL_DEBUG
    245 		hists[i++] = &scdebughist;
    246 #endif
    247 #ifdef BIOHIST
    248 		hists[i++] = &biohist;
    249 #endif
    250 		hists[i] = NULL;
    251 
    252 		kernhist_dump_histories(hists, pr);
    253 	} else {
    254 		kernhist_dump(h, pr);
    255 	}
    256 }
    257 
    258 #endif
    259