|
|
1.1 root 1: /*
2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
4: * All Rights Reserved.
5: *
6: * Permission to use, copy, modify and distribute this software and its
7: * documentation is hereby granted, provided that both the copyright
8: * notice and this permission notice appear in all copies of the
9: * software, derivative works or modified versions, and any portions
10: * thereof, and that both notices appear in supporting documentation.
11: *
12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15: *
16: * Carnegie Mellon requests users of this software to return to
17: *
18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
22: *
23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26:
27: #include <mach_kdb.h>
28: /*
29: * xpr silent tracing circular buffer.
30: */
31: #include <kern/xpr.h>
32: #include <kern/lock.h>
33: #include "cpu_number.h"
34: #include <machine/machspl.h>
35: #include <vm/vm_kern.h>
36:
37:
38: /*
39: * After a spontaneous reboot, it is desirable to look
40: * at the old xpr buffer. Assuming xprbootstrap allocates
41: * the buffer in the same place in physical memory and
42: * the reboot doesn't clear memory, this should work.
43: * xprptr will be reset, but the saved value should be OK.
44: * Just set xprenable false so the buffer isn't overwritten.
45: */
46:
47: decl_simple_lock_data(, xprlock)
48:
49: boolean_t xprenable = TRUE; /* Enable xpr tracing */
50: int nxprbufs = 0; /* Number of contiguous xprbufs allocated */
51: int xprflags = 0; /* Bit mask of xpr flags enabled */
52: struct xprbuf *xprbase; /* Pointer to circular buffer nxprbufs*sizeof(xprbuf)*/
53: struct xprbuf *xprptr; /* Currently allocated xprbuf */
54: struct xprbuf *xprlast; /* Pointer to end of circular buffer */
55:
56: /*VARARGS1*/
57: void xpr(msg, arg1, arg2, arg3, arg4, arg5)
58: char *msg;
59: int arg1, arg2, arg3, arg4, arg5;
60: {
61: register spl_t s;
62: register struct xprbuf *x;
63:
64: /* If we aren't initialized, ignore trace request */
65: if (!xprenable || (xprptr == 0))
66: return;
67: /* Guard against all interrupts and allocate next buffer. */
68: s = splhigh();
69: simple_lock(&xprlock);
70: x = xprptr++;
71: if (xprptr >= xprlast) {
72: /* wrap around */
73: xprptr = xprbase;
74: }
75: /* Save xprptr in allocated memory. */
76: *(struct xprbuf **)xprlast = xprptr;
77: simple_unlock(&xprlock);
78: splx(s);
79: x->msg = msg;
80: x->arg1 = arg1;
81: x->arg2 = arg2;
82: x->arg3 = arg3;
83: x->arg4 = arg4;
84: x->arg5 = arg5;
85: x->timestamp = XPR_TIMESTAMP;
86: x->cpuinfo = cpu_number();
87: }
88:
89: void xprbootstrap()
90: {
91: vm_offset_t addr;
92: vm_size_t size;
93: kern_return_t kr;
94:
95: simple_lock_init(&xprlock);
96: if (nxprbufs == 0)
97: return; /* assume XPR support not desired */
98:
99: /* leave room at the end for a saved copy of xprptr */
100: size = nxprbufs * sizeof(struct xprbuf) + sizeof xprptr;
101:
102: kr = kmem_alloc_wired(kernel_map, &addr, size);
103: if (kr != KERN_SUCCESS)
104: panic("xprbootstrap");
105:
106: if (xprenable) {
107: /*
108: * If xprenable is set (the default) then we zero
109: * the buffer so xpr_dump doesn't encounter bad pointers.
110: * If xprenable isn't set, then we preserve
111: * the original contents of the buffer. This is useful
112: * if memory survives reboots, so xpr_dump can show
113: * the previous buffer contents.
114: */
115:
116: bzero((char *) addr, size);
117: }
118:
119: xprbase = (struct xprbuf *) addr;
120: xprlast = &xprbase[nxprbufs];
121: xprptr = xprbase; /* setting xprptr enables tracing */
122: }
123:
124: int xprinitial = 0;
125:
126: void xprinit()
127: {
128: xprflags |= xprinitial;
129: }
130:
131: #if MACH_KDB
132: #include <machine/setjmp.h>
133:
134:
135: extern void db_printf();
136: extern jmp_buf_t *db_recover;
137:
138: /*
139: * Print current content of xpr buffers (KDB's sake)
140: * Use stack order to make it understandable.
141: *
142: * Called as "!xpr_dump" this dumps the kernel's xpr buffer.
143: * Called with arguments, it can dump xpr buffers in user tasks,
144: * assuming they use the same format as the kernel.
145: */
146: void xpr_dump(base, nbufs)
147: struct xprbuf *base;
148: int nbufs;
149: {
150: jmp_buf_t db_jmpbuf;
151: jmp_buf_t *prev;
152: struct xprbuf *last, *ptr;
153: register struct xprbuf *x;
154: int i;
155: spl_t s;
156:
157: if (base == 0) {
158: base = xprbase;
159: nbufs = nxprbufs;
160: }
161:
162: if (nbufs == 0)
163: return;
164:
165: if (base == xprbase) {
166: s = splhigh();
167: simple_lock(&xprlock);
168: }
169:
170: last = base + nbufs;
171: ptr = * (struct xprbuf **) last;
172:
173: prev = db_recover;
174: if (_setjmp(db_recover = &db_jmpbuf) == 0)
175: for (x = ptr, i = 0; i < nbufs; i++) {
176: if (--x < base)
177: x = last - 1;
178:
179: if (x->msg == 0)
180: break;
181:
182: db_printf("<%d:%x:%x> ", x - base, x->cpuinfo, x->timestamp);
183: db_printf(x->msg, x->arg1,x->arg2,x->arg3,x->arg4,x->arg5);
184: }
185: db_recover = prev;
186:
187: if (base == xprbase) {
188: simple_unlock(&xprlock);
189: (void) splx(s);
190: }
191: }
192: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.