]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/kern/kdebug.c
xnu-201.14.tar.gz
[apple/xnu.git] / bsd / kern / kdebug.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <machine/spl.h>
24
25#define HZ 100
26#include <mach/clock_types.h>
27#include <mach/mach_types.h>
28#include <machine/machine_routines.h>
29
30#include <sys/kdebug.h>
31#include <sys/errno.h>
32#include <sys/param.h>
33#include <sys/proc.h>
34#include <sys/vm.h>
35#include <sys/sysctl.h>
36
37#include <kern/thread.h>
38#include <kern/task.h>
39#include <vm/vm_kern.h>
40#include <sys/lock.h>
41
42/* kd_buf kd_buffer[kd_bufsize/sizeof(kd_buf)]; */
43kd_buf * kd_bufptr;
44unsigned int kd_buftomem=0;
45kd_buf * kd_buffer=0;
46kd_buf * kd_buflast;
47kd_buf * kd_readlast;
48unsigned int nkdbufs = 8192;
49unsigned int kd_bufsize = 0;
50unsigned int kdebug_flags = 0;
51unsigned int kdebug_enable=0;
52unsigned int kdebug_nolog=1;
53unsigned int kdlog_beg=0;
54unsigned int kdlog_end=0;
55unsigned int kdlog_value1=0;
56unsigned int kdlog_value2=0;
57unsigned int kdlog_value3=0;
58unsigned int kdlog_value4=0;
59
60unsigned long long kd_prev_timebase = 0LL;
61decl_simple_lock_data(,kd_trace_lock);
62
63kd_threadmap *kd_mapptr = 0;
64unsigned int kd_mapsize = 0;
65unsigned int kd_mapcount = 0;
66unsigned int kd_maptomem = 0;
67
68pid_t global_state_pid = -1; /* Used to control exclusive use of kd_buffer */
69
70#define DBG_FUNC_MASK 0xfffffffc
71
72#ifdef ppc
73extern natural_t rtclock_decrementer_min;
74#endif /* ppc */
75
76struct kdebug_args {
77 int code;
78 int arg1;
79 int arg2;
80 int arg3;
81 int arg4;
82 int arg5;
83};
84
85struct krt
86{
87 kd_threadmap *map; /* pointer to the map buffer */
88 int count;
89 int maxcount;
90 struct proc *p;
91};
92
93typedef struct krt krt_t;
94
95/* Support syscall SYS_kdebug_trace */
96kdebug_trace(p, uap, retval)
97 struct proc *p;
98 struct kdebug_args *uap;
99 register_t *retval;
100{
101 if (kdebug_nolog)
102 return(EINVAL);
103
104 kernel_debug(uap->code, uap->arg1, uap->arg2, uap->arg3, uap->arg4, 0);
105 return(0);
106}
107
108
109void
110kernel_debug(debugid, arg1, arg2, arg3, arg4, arg5)
111unsigned int debugid, arg1, arg2, arg3, arg4, arg5;
112{
113 kd_buf * kd;
114 struct proc *curproc;
115 int s;
116 unsigned long long now;
117 mach_timespec_t *tsp;
118
119 s = ml_set_interrupts_enabled(FALSE);
120
121 if (kdebug_nolog)
122 {
123 ml_set_interrupts_enabled(s);
124 return;
125 }
126
127 usimple_lock(&kd_trace_lock);
128 if (kdebug_flags & KDBG_PIDCHECK)
129 {
130 /* If kdebug flag is not set for current proc, return */
131 curproc = current_proc();
132 if ((curproc && !(curproc->p_flag & P_KDEBUG)) &&
133 ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE)))
134 {
135 usimple_unlock(&kd_trace_lock);
136 ml_set_interrupts_enabled(s);
137 return;
138 }
139 }
140 else if (kdebug_flags & KDBG_PIDEXCLUDE)
141 {
142 /* If kdebug flag is set for current proc, return */
143 curproc = current_proc();
144 if ((curproc && (curproc->p_flag & P_KDEBUG)) &&
145 ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE)))
146 {
147 usimple_unlock(&kd_trace_lock);
148 ml_set_interrupts_enabled(s);
149 return;
150 }
151 }
152
153 if (kdebug_flags & KDBG_RANGECHECK)
154 {
155 if ((debugid < kdlog_beg) || (debugid > kdlog_end)
156 && (debugid >> 24 != DBG_TRACE))
157 {
158 usimple_unlock(&kd_trace_lock);
159 ml_set_interrupts_enabled(s);
160 return;
161 }
162 }
163 else if (kdebug_flags & KDBG_VALCHECK)
164 {
165 if ((debugid & DBG_FUNC_MASK) != kdlog_value1 &&
166 (debugid & DBG_FUNC_MASK) != kdlog_value2 &&
167 (debugid & DBG_FUNC_MASK) != kdlog_value3 &&
168 (debugid & DBG_FUNC_MASK) != kdlog_value4 &&
169 (debugid >> 24 != DBG_TRACE))
170 {
171 usimple_unlock(&kd_trace_lock);
172 ml_set_interrupts_enabled(s);
173 return;
174 }
175 }
176 kd = kd_bufptr;
177 kd->debugid = debugid;
178 kd->arg1 = arg1;
179 kd->arg2 = arg2;
180 kd->arg3 = arg3;
181 kd->arg4 = arg4;
182 kd->arg5 = (int)current_thread();
183 if (cpu_number())
184 kd->arg5 |= KDBG_CPU_MASK;
185
186 ml_get_timebase((unsigned long long *)&kd->timestamp);
187
188 /* Watch for out of order timestamps */
189 now = (((unsigned long long)kd->timestamp.tv_sec) << 32) |
190 (unsigned long long)((unsigned int)(kd->timestamp.tv_nsec));
191
192 if (now < kd_prev_timebase)
193 {
194 /* timestamps are out of order -- adjust */
195 kd_prev_timebase++;
196 tsp = (mach_timespec_t *)&kd_prev_timebase;
197 kd->timestamp.tv_sec = tsp->tv_sec;
198 kd->timestamp.tv_nsec = tsp->tv_nsec;
199 }
200 else
201 {
202 /* Then just store the previous timestamp */
203 kd_prev_timebase = now;
204 }
205
206
207 kd_bufptr++;
208
209 if (kd_bufptr >= kd_buflast)
210 kd_bufptr = kd_buffer;
211 if (kd_bufptr == kd_readlast) {
212 if (kdebug_flags & KDBG_NOWRAP)
213 kdebug_nolog = 1;
214 kdebug_flags |= KDBG_WRAPPED;
215 }
216 usimple_unlock(&kd_trace_lock);
217 ml_set_interrupts_enabled(s);
218}
219
220void
221kernel_debug1(debugid, arg1, arg2, arg3, arg4, arg5)
222unsigned int debugid, arg1, arg2, arg3, arg4, arg5;
223{
224 kd_buf * kd;
225 struct proc *curproc;
226 int s;
227 unsigned long long now;
228 mach_timespec_t *tsp;
229
230 s = ml_set_interrupts_enabled(FALSE);
231
232 if (kdebug_nolog)
233 {
234 ml_set_interrupts_enabled(s);
235 return;
236 }
237
238 usimple_lock(&kd_trace_lock);
239 if (kdebug_flags & KDBG_PIDCHECK)
240 {
241 /* If kdebug flag is not set for current proc, return */
242 curproc = current_proc();
243 if ((curproc && !(curproc->p_flag & P_KDEBUG)) &&
244 ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE)))
245 {
246 usimple_unlock(&kd_trace_lock);
247 ml_set_interrupts_enabled(s);
248 return;
249 }
250 }
251 else if (kdebug_flags & KDBG_PIDEXCLUDE)
252 {
253 /* If kdebug flag is set for current proc, return */
254 curproc = current_proc();
255 if ((curproc && (curproc->p_flag & P_KDEBUG)) &&
256 ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE)))
257 {
258 usimple_unlock(&kd_trace_lock);
259 ml_set_interrupts_enabled(s);
260 return;
261 }
262 }
263
264 if (kdebug_flags & KDBG_RANGECHECK)
265 {
266 if ((debugid < kdlog_beg) || (debugid > kdlog_end)
267 && (debugid >> 24 != DBG_TRACE))
268 {
269 usimple_unlock(&kd_trace_lock);
270 ml_set_interrupts_enabled(s);
271 return;
272 }
273 }
274 else if (kdebug_flags & KDBG_VALCHECK)
275 {
276 if ((debugid & DBG_FUNC_MASK) != kdlog_value1 &&
277 (debugid & DBG_FUNC_MASK) != kdlog_value2 &&
278 (debugid & DBG_FUNC_MASK) != kdlog_value3 &&
279 (debugid & DBG_FUNC_MASK) != kdlog_value4 &&
280 (debugid >> 24 != DBG_TRACE))
281 {
282 usimple_unlock(&kd_trace_lock);
283 ml_set_interrupts_enabled(s);
284 return;
285 }
286 }
287
288 kd = kd_bufptr;
289 kd->debugid = debugid;
290 kd->arg1 = arg1;
291 kd->arg2 = arg2;
292 kd->arg3 = arg3;
293 kd->arg4 = arg4;
294 kd->arg5 = arg5;
295 ml_get_timebase((unsigned long long *)&kd->timestamp);
296
297 /* Watch for out of order timestamps */
298 now = (((unsigned long long)kd->timestamp.tv_sec) << 32) |
299 (unsigned long long)((unsigned int)(kd->timestamp.tv_nsec));
300
301 if (now < kd_prev_timebase)
302 {
303 /* timestamps are out of order -- adjust */
304 kd_prev_timebase++;
305 tsp = (mach_timespec_t *)&kd_prev_timebase;
306 kd->timestamp.tv_sec = tsp->tv_sec;
307 kd->timestamp.tv_nsec = tsp->tv_nsec;
308 }
309 else
310 {
311 /* Then just store the previous timestamp */
312 kd_prev_timebase = now;
313 }
314
315 kd_bufptr++;
316
317 if (kd_bufptr >= kd_buflast)
318 kd_bufptr = kd_buffer;
319 if (kd_bufptr == kd_readlast) {
320 if (kdebug_flags & KDBG_NOWRAP)
321 kdebug_nolog = 1;
322 kdebug_flags |= KDBG_WRAPPED;
323 }
324 usimple_unlock(&kd_trace_lock);
325 ml_set_interrupts_enabled(s);
326}
327
328
329kdbg_bootstrap()
330{
331 kd_bufsize = nkdbufs * sizeof(kd_buf);
332 if (kmem_alloc(kernel_map, &kd_buftomem,
333 (vm_size_t)kd_bufsize) == KERN_SUCCESS)
334 kd_buffer = (kd_buf *) kd_buftomem;
335 else kd_buffer= (kd_buf *) 0;
336 kdebug_flags &= ~KDBG_WRAPPED;
337 if (kd_buffer) {
338 simple_lock_init(&kd_trace_lock);
339 kdebug_flags |= (KDBG_INIT | KDBG_BUFINIT);
340 kd_bufptr = kd_buffer;
341 kd_buflast = &kd_bufptr[nkdbufs];
342 kd_readlast = kd_bufptr;
343 kd_prev_timebase = 0LL;
344 return(0);
345 } else {
346 kd_bufsize=0;
347 kdebug_flags &= ~(KDBG_INIT | KDBG_BUFINIT);
348 return(EINVAL);
349 }
350
351}
352
353kdbg_reinit()
354{
355 int x;
356 int ret=0;
357
358 kdebug_enable = 0;
359 kdebug_nolog = 1;
360
361 if ((kdebug_flags & KDBG_INIT) && (kdebug_flags & KDBG_BUFINIT) && kd_bufsize && kd_buffer)
362 kmem_free(kernel_map, (char *)kd_buffer, kd_bufsize);
363
364 if ((kdebug_flags & KDBG_MAPINIT) && kd_mapsize && kd_mapptr)
365 {
366 kmem_free(kernel_map, (char *)kd_mapptr, kd_mapsize);
367 kdebug_flags &= ~KDBG_MAPINIT;
368 kd_mapsize = 0;
369 kd_mapptr = (kd_threadmap *) 0;
370 kd_mapcount = 0;
371 }
372
373 ret= kdbg_bootstrap();
374
375 return(ret);
376}
377
378void kdbg_trace_string(struct proc *proc, long *arg1, long *arg2, long *arg3, long *arg4)
379{
380 int i;
381 char *dbg_nameptr;
382 int dbg_namelen;
383 long dbg_parms[4];
384
385 if (!proc)
386 {
387 *arg1 = 0;
388 *arg2 = 0;
389 *arg3 = 0;
390 *arg4 = 0;
391 return;
392 }
393
394 /* Collect the pathname for tracing */
395 dbg_nameptr = proc->p_comm;
396 dbg_namelen = strlen(proc->p_comm);
397 dbg_parms[0]=0L;
398 dbg_parms[1]=0L;
399 dbg_parms[2]=0L;
400 dbg_parms[3]=0L;
401
402 if(dbg_namelen > sizeof(dbg_parms))
403 dbg_namelen = sizeof(dbg_parms);
404
405 for(i=0;dbg_namelen > 0; i++)
406 {
407 dbg_parms[i]=*(long*)dbg_nameptr;
408 dbg_nameptr += sizeof(long);
409 dbg_namelen -= sizeof(long);
410 }
411
412 *arg1=dbg_parms[0];
413 *arg2=dbg_parms[1];
414 *arg3=dbg_parms[2];
415 *arg4=dbg_parms[3];
416}
417
418kdbg_resolve_map(thread_act_t th_act, krt_t *t)
419{
420 kd_threadmap *mapptr;
421
422 if(t->count < t->maxcount)
423 {
424 mapptr=&t->map[t->count];
425 mapptr->thread = (unsigned int)getshuttle_thread(th_act);
426 mapptr->valid = 1;
427 (void) strncpy (mapptr->command, t->p->p_comm,
428 sizeof(t->p->p_comm)-1);
429 mapptr->command[sizeof(t->p->p_comm)-1] = '\0';
430 t->count++;
431 }
432}
433
434void kdbg_mapinit()
435{
436 struct proc *p;
437 struct krt akrt;
438
439 if (kdebug_flags & KDBG_MAPINIT)
440 return;
441
442 /* Calculate size of thread map buffer */
443 for (p = allproc.lh_first, kd_mapcount=0; p;
444 p = p->p_list.le_next)
445 {
446 kd_mapcount += get_task_numacts((task_t)p->task);
447 }
448
449 kd_mapsize = kd_mapcount * sizeof(kd_threadmap);
450 if((kmem_alloc(kernel_map, & kd_maptomem,
451 (vm_size_t)kd_mapsize) == KERN_SUCCESS))
452 kd_mapptr = (kd_threadmap *) kd_maptomem;
453 else
454 kd_mapptr = (kd_threadmap *) 0;
455
456 if (kd_mapptr)
457 {
458 kdebug_flags |= KDBG_MAPINIT;
459 /* Initialize thread map data */
460 akrt.map = kd_mapptr;
461 akrt.count = 0;
462 akrt.maxcount = kd_mapcount;
463
464 for (p = allproc.lh_first; p; p = p->p_list.le_next)
465 {
466 akrt.p = p;
467 task_act_iterate_wth_args((task_t)p->task, kdbg_resolve_map, &akrt);
468 }
469 }
470}
471
472kdbg_clear()
473{
474int x;
475
476 /* Clean up the trace buffer */
477 global_state_pid = -1;
478 kdebug_enable = 0;
479 kdebug_nolog = 1;
480 kdebug_flags &= ~KDBG_BUFINIT;
481 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
482 kdebug_flags &= ~(KDBG_NOWRAP | KDBG_RANGECHECK | KDBG_VALCHECK);
483 kdebug_flags &= ~(KDBG_PIDCHECK | KDBG_PIDEXCLUDE);
484 kmem_free(kernel_map, (char *)kd_buffer, kd_bufsize);
485 kd_buffer = (kd_buf *)0;
486 kd_bufsize = 0;
487 kd_prev_timebase = 0LL;
488
489 /* Clean up the thread map buffer */
490 kdebug_flags &= ~KDBG_MAPINIT;
491 kmem_free(kernel_map, (char *)kd_mapptr, kd_mapsize);
492 kd_mapptr = (kd_threadmap *) 0;
493 kd_mapsize = 0;
494 kd_mapcount = 0;
495}
496
497kdbg_setpid(kd_regtype *kdr)
498{
499 pid_t pid;
500 int flag, ret=0;
501 struct proc *p;
502
503 pid = (pid_t)kdr->value1;
504 flag = (int)kdr->value2;
505
506 if (pid > 0)
507 {
508 if ((p = pfind(pid)) == NULL)
509 ret = ESRCH;
510 else
511 {
512 if (flag == 1) /* turn on pid check for this and all pids */
513 {
514 kdebug_flags |= KDBG_PIDCHECK;
515 kdebug_flags &= ~KDBG_PIDEXCLUDE;
516 p->p_flag |= P_KDEBUG;
517 }
518 else /* turn off pid check for this pid value */
519 {
520 /* Don't turn off all pid checking though */
521 /* kdebug_flags &= ~KDBG_PIDCHECK;*/
522 p->p_flag &= ~P_KDEBUG;
523 }
524 }
525 }
526 else
527 ret = EINVAL;
528 return(ret);
529}
530
531/* This is for pid exclusion in the trace buffer */
532kdbg_setpidex(kd_regtype *kdr)
533{
534 pid_t pid;
535 int flag, ret=0;
536 struct proc *p;
537
538 pid = (pid_t)kdr->value1;
539 flag = (int)kdr->value2;
540
541 if (pid > 0)
542 {
543 if ((p = pfind(pid)) == NULL)
544 ret = ESRCH;
545 else
546 {
547 if (flag == 1) /* turn on pid exclusion */
548 {
549 kdebug_flags |= KDBG_PIDEXCLUDE;
550 kdebug_flags &= ~KDBG_PIDCHECK;
551 p->p_flag |= P_KDEBUG;
552 }
553 else /* turn off pid exclusion for this pid value */
554 {
555 /* Don't turn off all pid exclusion though */
556 /* kdebug_flags &= ~KDBG_PIDEXCLUDE;*/
557 p->p_flag &= ~P_KDEBUG;
558 }
559 }
560 }
561 else
562 ret = EINVAL;
563 return(ret);
564}
565
566/* This is for setting a minimum decrementer value */
567kdbg_setrtcdec(kd_regtype *kdr)
568{
569 int ret=0;
570 natural_t decval;
571
572 decval = (natural_t)kdr->value1;
573
574 if (decval && decval < KDBG_MINRTCDEC)
575 ret = EINVAL;
576#ifdef ppc
577 else
578 rtclock_decrementer_min = decval;
579#else
580 else
581 ret = EOPNOTSUPP;
582#endif /* ppc */
583
584 return(ret);
585}
586
587kdbg_setreg(kd_regtype * kdr)
588{
589 int i,j, ret=0;
590 unsigned int val_1, val_2, val;
591 switch (kdr->type) {
592
593 case KDBG_CLASSTYPE :
594 val_1 = (kdr->value1 & 0xff);
595 val_2 = (kdr->value2 & 0xff);
596 kdlog_beg = (val_1<<24);
597 kdlog_end = (val_2<<24);
598 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
599 kdebug_flags &= ~KDBG_VALCHECK; /* Turn off specific value check */
600 kdebug_flags |= (KDBG_RANGECHECK | KDBG_CLASSTYPE);
601 break;
602 case KDBG_SUBCLSTYPE :
603 val_1 = (kdr->value1 & 0xff);
604 val_2 = (kdr->value2 & 0xff);
605 val = val_2 + 1;
606 kdlog_beg = ((val_1<<24) | (val_2 << 16));
607 kdlog_end = ((val_1<<24) | (val << 16));
608 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
609 kdebug_flags &= ~KDBG_VALCHECK; /* Turn off specific value check */
610 kdebug_flags |= (KDBG_RANGECHECK | KDBG_SUBCLSTYPE);
611 break;
612 case KDBG_RANGETYPE :
613 kdlog_beg = (kdr->value1);
614 kdlog_end = (kdr->value2);
615 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
616 kdebug_flags &= ~KDBG_VALCHECK; /* Turn off specific value check */
617 kdebug_flags |= (KDBG_RANGECHECK | KDBG_RANGETYPE);
618 break;
619 case KDBG_VALCHECK:
620 kdlog_value1 = (kdr->value1);
621 kdlog_value2 = (kdr->value2);
622 kdlog_value3 = (kdr->value3);
623 kdlog_value4 = (kdr->value4);
624 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
625 kdebug_flags &= ~KDBG_RANGECHECK; /* Turn off range check */
626 kdebug_flags |= KDBG_VALCHECK; /* Turn on specific value check */
627 break;
628 case KDBG_TYPENONE :
629 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
630 kdlog_beg = 0;
631 kdlog_end = 0;
632 break;
633 default :
634 ret = EINVAL;
635 break;
636 }
637 return(ret);
638}
639
640kdbg_getreg(kd_regtype * kdr)
641{
642 int i,j, ret=0;
643 unsigned int val_1, val_2, val;
644#if 0
645 switch (kdr->type) {
646 case KDBG_CLASSTYPE :
647 val_1 = (kdr->value1 & 0xff);
648 val_2 = val_1 + 1;
649 kdlog_beg = (val_1<<24);
650 kdlog_end = (val_2<<24);
651 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
652 kdebug_flags |= (KDBG_RANGECHECK | KDBG_CLASSTYPE);
653 break;
654 case KDBG_SUBCLSTYPE :
655 val_1 = (kdr->value1 & 0xff);
656 val_2 = (kdr->value2 & 0xff);
657 val = val_2 + 1;
658 kdlog_beg = ((val_1<<24) | (val_2 << 16));
659 kdlog_end = ((val_1<<24) | (val << 16));
660 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
661 kdebug_flags |= (KDBG_RANGECHECK | KDBG_SUBCLSTYPE);
662 break;
663 case KDBG_RANGETYPE :
664 kdlog_beg = (kdr->value1);
665 kdlog_end = (kdr->value2);
666 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
667 kdebug_flags |= (KDBG_RANGECHECK | KDBG_RANGETYPE);
668 break;
669 case KDBG_TYPENONE :
670 kdebug_flags &= (unsigned int)~KDBG_CKTYPES;
671 kdlog_beg = 0;
672 kdlog_end = 0;
673 break;
674 default :
675 ret = EINVAL;
676 break;
677 }
678#endif /* 0 */
679 return(EINVAL);
680}
681
682
683
684kdbg_readmap(kd_threadmap *buffer, size_t *number)
685{
686 int avail = *number;
687 int ret = 0;
688 int count = 0;
689
690 count = avail/sizeof (kd_threadmap);
691
692 if (count && (count <= kd_mapcount))
693 {
694 if((kdebug_flags & KDBG_MAPINIT) && kd_mapsize && kd_mapptr)
695 {
696 if (*number < kd_mapsize)
697 ret=EINVAL;
698 else
699 {
700 if (copyout(kd_mapptr, buffer, kd_mapsize))
701 ret=EINVAL;
702 }
703 }
704 else
705 ret=EINVAL;
706 }
707 else
708 ret=EINVAL;
709
710 if ((kdebug_flags & KDBG_MAPINIT) && kd_mapsize && kd_mapptr)
711 {
712 kmem_free(kernel_map, (char *)kd_mapptr, kd_mapsize);
713 kdebug_flags &= ~KDBG_MAPINIT;
714 kd_mapsize = 0;
715 kd_mapptr = (kd_threadmap *) 0;
716 kd_mapcount = 0;
717 }
718
719 return(ret);
720}
721
722
723kdbg_control(name, namelen, where, sizep)
724int *name;
725u_int namelen;
726char *where;
727size_t *sizep;
728{
729int ret=0;
730int size=*sizep;
731int max_entries;
732unsigned int value = name[1];
733kd_regtype kd_Reg;
734kbufinfo_t kd_bufinfo;
735
736pid_t curpid;
737struct proc *p, *curproc;
738
739 if(curproc = current_proc())
740 curpid = curproc->p_pid;
741 else
742 return (ESRCH);
743
744 if (global_state_pid == -1)
745 global_state_pid = curpid;
746 else if (global_state_pid != curpid)
747 {
748 if((p = pfind(global_state_pid)) == NULL)
749 {
750 /* The global pid no longer exists */
751 global_state_pid = curpid;
752 }
753 else
754 {
755 /* The global pid exists, deny this request */
756 return(EBUSY);
757 }
758 }
759
760 switch(name[0]) {
761 case KERN_KDEFLAGS:
762 value &= KDBG_USERFLAGS;
763 kdebug_flags |= value;
764 break;
765 case KERN_KDDFLAGS:
766 value &= KDBG_USERFLAGS;
767 kdebug_flags &= ~value;
768 break;
769 case KERN_KDENABLE: /* used to enable or disable */
770 if (value)
771 {
772 /* enable only if buffer is initialized */
773 if (!(kdebug_flags & KDBG_BUFINIT))
774 {
775 ret=EINVAL;
776 break;
777 }
778 }
779 kdebug_enable=(value)?1:0;
780 kdebug_nolog = (value)?0:1;
781 if (kdebug_enable)
782 kdbg_mapinit();
783 break;
784 case KERN_KDSETBUF:
785 /* We allow a maximum buffer size of 25% of memory */
786 /* 'value' is the desired number of trace entries */
787 max_entries = (mem_size/4) / sizeof(kd_buf);
788 if (value <= max_entries)
789 nkdbufs = value;
790 else
791 nkdbufs = max_entries;
792 break;
793 case KERN_KDGETBUF:
794 if(size < sizeof(kbufinfo_t)) {
795 ret=EINVAL;
796 break;
797 }
798 kd_bufinfo.nkdbufs = nkdbufs;
799 kd_bufinfo.nkdthreads = kd_mapsize / sizeof(kd_threadmap);
800 kd_bufinfo.nolog = kdebug_nolog;
801 kd_bufinfo.flags = kdebug_flags;
802 if(copyout (&kd_bufinfo, where, sizeof(kbufinfo_t))) {
803 ret=EINVAL;
804 }
805 break;
806 case KERN_KDSETUP:
807 ret=kdbg_reinit();
808 break;
809 case KERN_KDREMOVE:
810 kdbg_clear();
811 break;
812 case KERN_KDSETREG:
813 if(size < sizeof(kd_regtype)) {
814 ret=EINVAL;
815 break;
816 }
817 if (copyin(where, &kd_Reg, sizeof(kd_regtype))) {
818 ret= EINVAL;
819 break;
820 }
821 ret = kdbg_setreg(&kd_Reg);
822 break;
823 case KERN_KDGETREG:
824 if(size < sizeof(kd_regtype)) {
825 ret = EINVAL;
826 break;
827 }
828 ret = kdbg_getreg(&kd_Reg);
829 if (copyout(&kd_Reg, where, sizeof(kd_regtype))){
830 ret=EINVAL;
831 }
832 break;
833 case KERN_KDREADTR:
834 ret = kdbg_read(where, sizep);
835 break;
836 case KERN_KDPIDTR:
837 if (size < sizeof(kd_regtype)) {
838 ret = EINVAL;
839 break;
840 }
841 if (copyin(where, &kd_Reg, sizeof(kd_regtype))) {
842 ret= EINVAL;
843 break;
844 }
845 ret = kdbg_setpid(&kd_Reg);
846 break;
847 case KERN_KDPIDEX:
848 if (size < sizeof(kd_regtype)) {
849 ret = EINVAL;
850 break;
851 }
852 if (copyin(where, &kd_Reg, sizeof(kd_regtype))) {
853 ret= EINVAL;
854 break;
855 }
856 ret = kdbg_setpidex(&kd_Reg);
857 break;
858 case KERN_KDTHRMAP:
859 ret = kdbg_readmap((kd_threadmap *)where, sizep);
860 break;
861 case KERN_KDSETRTCDEC:
862 if (size < sizeof(kd_regtype)) {
863 ret = EINVAL;
864 break;
865 }
866 if (copyin(where, &kd_Reg, sizeof(kd_regtype))) {
867 ret= EINVAL;
868 break;
869 }
870 ret = kdbg_setrtcdec(&kd_Reg);
871 break;
872
873 default:
874 ret= EINVAL;
875 }
876 return(ret);
877}
878
879kdbg_read(kd_buf * buffer, size_t *number)
880{
881int avail=*number;
882int count=0;
883int copycount=0;
884int totalcount=0;
885int s;
886unsigned int my_kdebug_flags;
887kd_buf * my_kd_bufptr;
888
889 s = ml_set_interrupts_enabled(FALSE);
890 usimple_lock(&kd_trace_lock);
891 my_kdebug_flags = kdebug_flags;
892 my_kd_bufptr = kd_bufptr;
893 usimple_unlock(&kd_trace_lock);
894 ml_set_interrupts_enabled(s);
895
896 count = avail/sizeof(kd_buf);
897 if (count) {
898 if ((my_kdebug_flags & KDBG_BUFINIT) && kd_bufsize && kd_buffer) {
899 if (count > nkdbufs)
900 count = nkdbufs;
901 if (!(my_kdebug_flags & KDBG_WRAPPED) && (my_kd_bufptr > kd_readlast))
902 {
903 copycount = my_kd_bufptr-kd_readlast;
904 if (copycount > count)
905 copycount = count;
906
907 if (copyout(kd_readlast, buffer, copycount * sizeof(kd_buf)))
908 {
909 *number = 0;
910 return(EINVAL);
911 }
912 kd_readlast += copycount;
913 *number = copycount;
914 return(0);
915 }
916 else if (!(my_kdebug_flags & KDBG_WRAPPED) && (my_kd_bufptr == kd_readlast))
917 {
918 *number = 0;
919 return(0);
920 }
921 else
922 {
923 if (my_kdebug_flags & KDBG_WRAPPED)
924 {
925 kd_readlast = my_kd_bufptr;
926 kdebug_flags &= ~KDBG_WRAPPED;
927 }
928
929 /* Note that by setting kd_readlast equal to my_kd_bufptr,
930 we now treat the kd_buffer read the same as if we weren't
931 wrapped and my_kd_bufptr was less than kd_readlast.
932 */
933
934 /* first copyout from readlast to end of kd_buffer */
935 copycount = kd_buflast - kd_readlast;
936 if (copycount > count)
937 copycount = count;
938 if (copyout(kd_readlast, buffer, copycount * sizeof(kd_buf)))
939 {
940 *number = 0;
941 return(EINVAL);
942 }
943 buffer += copycount;
944 count -= copycount;
945 totalcount = copycount;
946 kd_readlast += copycount;
947 if (kd_readlast == kd_buflast)
948 kd_readlast = kd_buffer;
949 if (count == 0)
950 {
951 *number = totalcount;
952 return(0);
953 }
954
955 /* second copyout from top of kd_buffer to bufptr */
956 copycount = my_kd_bufptr - kd_readlast;
957 if (copycount > count)
958 copycount = count;
959 if (copycount == 0)
960 {
961 *number = totalcount;
962 return(0);
963 }
964 if (copyout(kd_readlast, buffer, copycount * sizeof(kd_buf)))
965 {
966 return(EINVAL);
967 }
968 kd_readlast += copycount;
969 totalcount += copycount;
970 *number = totalcount;
971 return(0);
972 }
973 } /* end if KDBG_BUFINIT */
974 } /* end if count */
975 return (EINVAL);
976}