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