123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * Mach Operating System
- * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * xpr silent tracing circular buffer.
- */
- #include <string.h>
- #include <kern/debug.h>
- #include <kern/xpr.h>
- #include <kern/lock.h>
- #include "cpu_number.h"
- #include <machine/machspl.h>
- #include <vm/vm_kern.h>
- /*
- * After a spontaneous reboot, it is desirable to look
- * at the old xpr buffer. Assuming xprbootstrap allocates
- * the buffer in the same place in physical memory and
- * the reboot doesn't clear memory, this should work.
- * xprptr will be reset, but the saved value should be OK.
- * Just set xprenable false so the buffer isn't overwritten.
- */
- decl_simple_lock_data(, xprlock)
- boolean_t xprenable = TRUE; /* Enable xpr tracing */
- int nxprbufs = 0; /* Number of contiguous xprbufs allocated */
- int xprflags = 0; /* Bit mask of xpr flags enabled */
- struct xprbuf *xprbase; /* Pointer to circular buffer nxprbufs*sizeof(xprbuf)*/
- struct xprbuf *xprptr; /* Currently allocated xprbuf */
- struct xprbuf *xprlast; /* Pointer to end of circular buffer */
- /*VARARGS1*/
- void xpr(
- char *msg,
- int arg1,
- int arg2,
- int arg3,
- int arg4,
- int arg5)
- {
- spl_t s;
- struct xprbuf *x;
- /* If we aren't initialized, ignore trace request */
- if (!xprenable || (xprptr == 0))
- return;
- /* Guard against all interrupts and allocate next buffer. */
- s = splhigh();
- simple_lock(&xprlock);
- x = xprptr++;
- if (xprptr >= xprlast) {
- /* wrap around */
- xprptr = xprbase;
- }
- /* Save xprptr in allocated memory. */
- *(struct xprbuf **)xprlast = xprptr;
- simple_unlock(&xprlock);
- splx(s);
- x->msg = msg;
- x->arg1 = arg1;
- x->arg2 = arg2;
- x->arg3 = arg3;
- x->arg4 = arg4;
- x->arg5 = arg5;
- x->timestamp = XPR_TIMESTAMP;
- x->cpuinfo = cpu_number();
- }
- void xprbootstrap(void)
- {
- vm_offset_t addr;
- vm_size_t size;
- kern_return_t kr;
- simple_lock_init(&xprlock);
- if (nxprbufs == 0)
- return; /* assume XPR support not desired */
- /* leave room at the end for a saved copy of xprptr */
- size = nxprbufs * sizeof(struct xprbuf) + sizeof xprptr;
- kr = kmem_alloc_wired(kernel_map, &addr, size);
- if (kr != KERN_SUCCESS)
- panic("xprbootstrap");
- if (xprenable) {
- /*
- * If xprenable is set (the default) then we zero
- * the buffer so xpr_dump doesn't encounter bad pointers.
- * If xprenable isn't set, then we preserve
- * the original contents of the buffer. This is useful
- * if memory survives reboots, so xpr_dump can show
- * the previous buffer contents.
- */
- memset((void *) addr, 0, size);
- }
- xprbase = (struct xprbuf *) addr;
- xprlast = &xprbase[nxprbufs];
- xprptr = xprbase; /* setting xprptr enables tracing */
- }
- int xprinitial = 0;
- void xprinit(void)
- {
- xprflags |= xprinitial;
- }
- #if MACH_KDB
- #include <machine/setjmp.h>
- #include <ddb/db_output.h>
- extern jmp_buf_t *db_recover;
- /*
- * Print current content of xpr buffers (KDB's sake)
- * Use stack order to make it understandable.
- *
- * Called as "!xpr_dump" this dumps the kernel's xpr buffer.
- * Called with arguments, it can dump xpr buffers in user tasks,
- * assuming they use the same format as the kernel.
- */
- void xpr_dump(
- struct xprbuf *base,
- int nbufs)
- {
- jmp_buf_t db_jmpbuf;
- jmp_buf_t *prev;
- struct xprbuf *last, *ptr;
- struct xprbuf *x;
- int i;
- spl_t s = s;
- if (base == 0) {
- base = xprbase;
- nbufs = nxprbufs;
- }
- if (nbufs == 0)
- return;
- if (base == xprbase) {
- s = splhigh();
- simple_lock(&xprlock);
- }
- last = base + nbufs;
- ptr = * (struct xprbuf **) last;
- prev = db_recover;
- if (_setjmp(db_recover = &db_jmpbuf) == 0)
- for (x = ptr, i = 0; i < nbufs; i++) {
- if (--x < base)
- x = last - 1;
- if (x->msg == 0)
- break;
- db_printf("<%d:%x:%x> ", x - base, x->cpuinfo, x->timestamp);
- db_printf(x->msg, x->arg1,x->arg2,x->arg3,x->arg4,x->arg5);
- }
- db_recover = prev;
- if (base == xprbase) {
- simple_unlock(&xprlock);
- (void) splx(s);
- }
- }
- #endif /* MACH_KDB */
|