xpr.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 Software.Distribution@CS.CMU.EDU
  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. * xpr silent tracing circular buffer.
  28. */
  29. #include <string.h>
  30. #include <kern/debug.h>
  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. * After a spontaneous reboot, it is desirable to look
  38. * at the old xpr buffer. Assuming xprbootstrap allocates
  39. * the buffer in the same place in physical memory and
  40. * the reboot doesn't clear memory, this should work.
  41. * xprptr will be reset, but the saved value should be OK.
  42. * Just set xprenable false so the buffer isn't overwritten.
  43. */
  44. decl_simple_lock_data(, xprlock)
  45. boolean_t xprenable = TRUE; /* Enable xpr tracing */
  46. int nxprbufs = 0; /* Number of contiguous xprbufs allocated */
  47. int xprflags = 0; /* Bit mask of xpr flags enabled */
  48. struct xprbuf *xprbase; /* Pointer to circular buffer nxprbufs*sizeof(xprbuf)*/
  49. struct xprbuf *xprptr; /* Currently allocated xprbuf */
  50. struct xprbuf *xprlast; /* Pointer to end of circular buffer */
  51. /*VARARGS1*/
  52. void xpr(
  53. char *msg,
  54. int arg1,
  55. int arg2,
  56. int arg3,
  57. int arg4,
  58. int arg5)
  59. {
  60. spl_t s;
  61. struct xprbuf *x;
  62. /* If we aren't initialized, ignore trace request */
  63. if (!xprenable || (xprptr == 0))
  64. return;
  65. /* Guard against all interrupts and allocate next buffer. */
  66. s = splhigh();
  67. simple_lock(&xprlock);
  68. x = xprptr++;
  69. if (xprptr >= xprlast) {
  70. /* wrap around */
  71. xprptr = xprbase;
  72. }
  73. /* Save xprptr in allocated memory. */
  74. *(struct xprbuf **)xprlast = xprptr;
  75. simple_unlock(&xprlock);
  76. splx(s);
  77. x->msg = msg;
  78. x->arg1 = arg1;
  79. x->arg2 = arg2;
  80. x->arg3 = arg3;
  81. x->arg4 = arg4;
  82. x->arg5 = arg5;
  83. x->timestamp = XPR_TIMESTAMP;
  84. x->cpuinfo = cpu_number();
  85. }
  86. void xprbootstrap(void)
  87. {
  88. vm_offset_t addr;
  89. vm_size_t size;
  90. kern_return_t kr;
  91. simple_lock_init(&xprlock);
  92. if (nxprbufs == 0)
  93. return; /* assume XPR support not desired */
  94. /* leave room at the end for a saved copy of xprptr */
  95. size = nxprbufs * sizeof(struct xprbuf) + sizeof xprptr;
  96. kr = kmem_alloc_wired(kernel_map, &addr, size);
  97. if (kr != KERN_SUCCESS)
  98. panic("xprbootstrap");
  99. if (xprenable) {
  100. /*
  101. * If xprenable is set (the default) then we zero
  102. * the buffer so xpr_dump doesn't encounter bad pointers.
  103. * If xprenable isn't set, then we preserve
  104. * the original contents of the buffer. This is useful
  105. * if memory survives reboots, so xpr_dump can show
  106. * the previous buffer contents.
  107. */
  108. memset((void *) addr, 0, size);
  109. }
  110. xprbase = (struct xprbuf *) addr;
  111. xprlast = &xprbase[nxprbufs];
  112. xprptr = xprbase; /* setting xprptr enables tracing */
  113. }
  114. int xprinitial = 0;
  115. void xprinit(void)
  116. {
  117. xprflags |= xprinitial;
  118. }
  119. #if MACH_KDB
  120. #include <machine/setjmp.h>
  121. #include <ddb/db_output.h>
  122. extern jmp_buf_t *db_recover;
  123. /*
  124. * Print current content of xpr buffers (KDB's sake)
  125. * Use stack order to make it understandable.
  126. *
  127. * Called as "!xpr_dump" this dumps the kernel's xpr buffer.
  128. * Called with arguments, it can dump xpr buffers in user tasks,
  129. * assuming they use the same format as the kernel.
  130. */
  131. void xpr_dump(
  132. struct xprbuf *base,
  133. int nbufs)
  134. {
  135. jmp_buf_t db_jmpbuf;
  136. jmp_buf_t *prev;
  137. struct xprbuf *last, *ptr;
  138. struct xprbuf *x;
  139. int i;
  140. spl_t s = s;
  141. if (base == 0) {
  142. base = xprbase;
  143. nbufs = nxprbufs;
  144. }
  145. if (nbufs == 0)
  146. return;
  147. if (base == xprbase) {
  148. s = splhigh();
  149. simple_lock(&xprlock);
  150. }
  151. last = base + nbufs;
  152. ptr = * (struct xprbuf **) last;
  153. prev = db_recover;
  154. if (_setjmp(db_recover = &db_jmpbuf) == 0)
  155. for (x = ptr, i = 0; i < nbufs; i++) {
  156. if (--x < base)
  157. x = last - 1;
  158. if (x->msg == 0)
  159. break;
  160. db_printf("<%d:%x:%x> ", x - base, x->cpuinfo, x->timestamp);
  161. db_printf(x->msg, x->arg1,x->arg2,x->arg3,x->arg4,x->arg5);
  162. }
  163. db_recover = prev;
  164. if (base == xprbase) {
  165. simple_unlock(&xprlock);
  166. (void) splx(s);
  167. }
  168. }
  169. #endif /* MACH_KDB */