aboutsummaryrefslogtreecommitdiff
path: root/kern/xpr.c
diff options
context:
space:
mode:
authorPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
committerPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
commit5e0b8d508ed51004bd836384293be00950ee62c9 (patch)
treee3f16b1aa8b7177032ce3ec429fbad2b1d92a876 /kern/xpr.c
downloadgnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.gz
gnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.bz2
init gnumach copy
Diffstat (limited to 'kern/xpr.c')
-rw-r--r--kern/xpr.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/kern/xpr.c b/kern/xpr.c
new file mode 100644
index 0000000..1b551eb
--- /dev/null
+++ b/kern/xpr.c
@@ -0,0 +1,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.
+ */
+
+def_simple_lock_data(static, 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 */