1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
|
/*
* 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 */
|