initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / s390 / kernel / debug.c
blob8669d6c3e8d3face580acf0d57eed898d1a20501
1 /*
2 * arch/s390/kernel/debug.c
3 * S/390 debug facility
5 * Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
6 * IBM Corporation
7 * Author(s): Michael Holzheu (holzheu@de.ibm.com),
8 * Holger Smolinski (Holger.Smolinski@de.ibm.com)
10 * Bugreports to: <Linux390@de.ibm.com>
13 #include <linux/config.h>
14 #include <linux/stddef.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/slab.h>
18 #include <linux/ctype.h>
19 #include <asm/uaccess.h>
20 #include <asm/semaphore.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
25 #include <asm/debug.h>
27 #define DEBUG_PROLOG_ENTRY -1
29 /* typedefs */
31 typedef struct file_private_info {
32 loff_t offset; /* offset of last read in file */
33 int act_area; /* number of last formated area */
34 int act_entry; /* last formated entry (offset */
35 /* relative to beginning of last */
36 /* formated area) */
37 size_t act_entry_offset; /* up to this offset we copied */
38 /* in last read the last formated */
39 /* entry to userland */
40 char temp_buf[2048]; /* buffer for output */
41 debug_info_t *debug_info_org; /* original debug information */
42 debug_info_t *debug_info_snap; /* snapshot of debug information */
43 struct debug_view *view; /* used view of debug info */
44 } file_private_info_t;
46 typedef struct
48 char *string;
49 /*
50 * This assumes that all args are converted into longs
51 * on L/390 this is the case for all types of parameter
52 * except of floats, and long long (32 bit)
55 long args[0];
56 } debug_sprintf_entry_t;
59 extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
61 /* internal function prototyes */
63 static int debug_init(void);
64 static ssize_t debug_output(struct file *file, char __user *user_buf,
65 size_t user_len, loff_t * offset);
66 static ssize_t debug_input(struct file *file, const char __user *user_buf,
67 size_t user_len, loff_t * offset);
68 static int debug_open(struct inode *inode, struct file *file);
69 static int debug_close(struct inode *inode, struct file *file);
70 static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
71 static void debug_info_get(debug_info_t *);
72 static void debug_info_put(debug_info_t *);
73 static int debug_prolog_level_fn(debug_info_t * id,
74 struct debug_view *view, char *out_buf);
75 static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
76 struct file *file, const char __user *user_buf,
77 size_t user_buf_size, loff_t * offset);
78 static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
79 struct file *file, const char __user *user_buf,
80 size_t user_buf_size, loff_t * offset);
81 static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
82 char *out_buf, const char *in_buf);
83 static int debug_raw_format_fn(debug_info_t * id,
84 struct debug_view *view, char *out_buf,
85 const char *in_buf);
86 static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
87 int area, debug_entry_t * entry, char *out_buf);
89 static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
90 char *out_buf, debug_sprintf_entry_t *curr_event);
92 /* globals */
94 struct debug_view debug_raw_view = {
95 "raw",
96 NULL,
97 &debug_raw_header_fn,
98 &debug_raw_format_fn,
99 NULL,
100 NULL
103 struct debug_view debug_hex_ascii_view = {
104 "hex_ascii",
105 NULL,
106 &debug_dflt_header_fn,
107 &debug_hex_ascii_format_fn,
108 NULL,
109 NULL
112 struct debug_view debug_level_view = {
113 "level",
114 &debug_prolog_level_fn,
115 NULL,
116 NULL,
117 &debug_input_level_fn,
118 NULL
121 struct debug_view debug_flush_view = {
122 "flush",
123 NULL,
124 NULL,
125 NULL,
126 &debug_input_flush_fn,
127 NULL
130 struct debug_view debug_sprintf_view = {
131 "sprintf",
132 NULL,
133 &debug_dflt_header_fn,
134 (debug_format_proc_t*)&debug_sprintf_format_fn,
135 NULL,
136 NULL
140 unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
142 /* static globals */
144 static debug_info_t *debug_area_first = NULL;
145 static debug_info_t *debug_area_last = NULL;
146 DECLARE_MUTEX(debug_lock);
148 static int initialized;
150 static struct file_operations debug_file_ops = {
151 .owner = THIS_MODULE,
152 .read = debug_output,
153 .write = debug_input,
154 .open = debug_open,
155 .release = debug_close,
158 static struct proc_dir_entry *debug_proc_root_entry;
160 /* functions */
163 * debug_info_alloc
164 * - alloc new debug-info
167 static debug_info_t* debug_info_alloc(char *name, int page_order,
168 int nr_areas, int buf_size)
170 debug_info_t* rc;
171 int i;
173 /* alloc everything */
175 rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
176 if(!rc)
177 goto fail_malloc_rc;
178 rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
179 if(!rc->active_entry)
180 goto fail_malloc_active_entry;
181 memset(rc->active_entry, 0, nr_areas * sizeof(int));
182 rc->areas = (debug_entry_t **) kmalloc(nr_areas *
183 sizeof(debug_entry_t *),
184 GFP_ATOMIC);
185 if (!rc->areas)
186 goto fail_malloc_areas;
187 for (i = 0; i < nr_areas; i++) {
188 rc->areas[i] = (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
189 page_order);
190 if (!rc->areas[i]) {
191 for (i--; i >= 0; i--) {
192 free_pages((unsigned long) rc->areas[i],
193 page_order);
195 goto fail_malloc_areas2;
196 } else {
197 memset(rc->areas[i], 0, PAGE_SIZE << page_order);
201 /* initialize members */
203 spin_lock_init(&rc->lock);
204 rc->page_order = page_order;
205 rc->nr_areas = nr_areas;
206 rc->active_area = 0;
207 rc->level = DEBUG_DEFAULT_LEVEL;
208 rc->buf_size = buf_size;
209 rc->entry_size = sizeof(debug_entry_t) + buf_size;
210 strlcpy(rc->name, name, sizeof(rc->name));
211 memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
212 #ifdef CONFIG_PROC_FS
213 memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
214 sizeof(struct proc_dir_entry*));
215 #endif /* CONFIG_PROC_FS */
216 atomic_set(&(rc->ref_count), 0);
218 return rc;
220 fail_malloc_areas2:
221 kfree(rc->areas);
222 fail_malloc_areas:
223 kfree(rc->active_entry);
224 fail_malloc_active_entry:
225 kfree(rc);
226 fail_malloc_rc:
227 return NULL;
231 * debug_info_free
232 * - free memory debug-info
235 static void debug_info_free(debug_info_t* db_info){
236 int i;
237 for (i = 0; i < db_info->nr_areas; i++) {
238 free_pages((unsigned long) db_info->areas[i],
239 db_info->page_order);
241 kfree(db_info->areas);
242 kfree(db_info->active_entry);
243 kfree(db_info);
247 * debug_info_create
248 * - create new debug-info
251 static debug_info_t* debug_info_create(char *name, int page_order,
252 int nr_areas, int buf_size)
254 debug_info_t* rc;
256 rc = debug_info_alloc(name, page_order, nr_areas, buf_size);
257 if(!rc)
258 goto out;
261 /* create proc rood directory */
262 rc->proc_root_entry = proc_mkdir(rc->name, debug_proc_root_entry);
264 /* append new element to linked list */
265 if (debug_area_first == NULL) {
266 /* first element in list */
267 debug_area_first = rc;
268 rc->prev = NULL;
269 } else {
270 /* append element to end of list */
271 debug_area_last->next = rc;
272 rc->prev = debug_area_last;
274 debug_area_last = rc;
275 rc->next = NULL;
277 debug_info_get(rc);
278 out:
279 return rc;
283 * debug_info_copy
284 * - copy debug-info
287 static debug_info_t* debug_info_copy(debug_info_t* in)
289 int i;
290 debug_info_t* rc;
291 rc = debug_info_alloc(in->name, in->page_order,
292 in->nr_areas, in->buf_size);
293 if(!rc)
294 goto out;
296 for(i = 0; i < in->nr_areas; i++){
297 memcpy(rc->areas[i],in->areas[i], PAGE_SIZE << in->page_order);
299 out:
300 return rc;
304 * debug_info_get
305 * - increments reference count for debug-info
308 static void debug_info_get(debug_info_t * db_info)
310 if (db_info)
311 atomic_inc(&db_info->ref_count);
315 * debug_info_put:
316 * - decreases reference count for debug-info and frees it if necessary
319 static void debug_info_put(debug_info_t *db_info)
321 int i;
323 if (!db_info)
324 return;
325 if (atomic_dec_and_test(&db_info->ref_count)) {
326 #ifdef DEBUG
327 printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
328 db_info, db_info->name);
329 #endif
330 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
331 if (db_info->views[i] == NULL)
332 continue;
333 #ifdef CONFIG_PROC_FS
334 remove_proc_entry(db_info->proc_entries[i]->name,
335 db_info->proc_root_entry);
336 #endif
338 #ifdef CONFIG_PROC_FS
339 remove_proc_entry(db_info->proc_root_entry->name,
340 debug_proc_root_entry);
341 #endif
342 if(db_info == debug_area_first)
343 debug_area_first = db_info->next;
344 if(db_info == debug_area_last)
345 debug_area_last = db_info->prev;
346 if(db_info->prev) db_info->prev->next = db_info->next;
347 if(db_info->next) db_info->next->prev = db_info->prev;
348 debug_info_free(db_info);
353 * debug_format_entry:
354 * - format one debug entry and return size of formated data
357 static int debug_format_entry(file_private_info_t *p_info)
359 debug_info_t *id_org = p_info->debug_info_org;
360 debug_info_t *id_snap = p_info->debug_info_snap;
361 struct debug_view *view = p_info->view;
362 debug_entry_t *act_entry;
363 size_t len = 0;
364 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
365 /* print prolog */
366 if (view->prolog_proc)
367 len += view->prolog_proc(id_org, view,p_info->temp_buf);
368 goto out;
371 act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area] +
372 p_info->act_entry);
374 if (act_entry->id.stck == 0LL)
375 goto out; /* empty entry */
376 if (view->header_proc)
377 len += view->header_proc(id_org, view, p_info->act_area,
378 act_entry, p_info->temp_buf + len);
379 if (view->format_proc)
380 len += view->format_proc(id_org, view, p_info->temp_buf + len,
381 DEBUG_DATA(act_entry));
382 out:
383 return len;
387 * debug_next_entry:
388 * - goto next entry in p_info
391 extern inline int debug_next_entry(file_private_info_t *p_info)
393 debug_info_t *id = p_info->debug_info_snap;
394 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
395 p_info->act_entry = 0;
396 goto out;
398 if ((p_info->act_entry += id->entry_size)
399 > ((PAGE_SIZE << (id->page_order))
400 - id->entry_size)){
402 /* next area */
403 p_info->act_entry = 0;
404 p_info->act_area++;
405 if(p_info->act_area >= id->nr_areas)
406 return 1;
408 out:
409 return 0;
413 * debug_output:
414 * - called for user read()
415 * - copies formated debug entries to the user buffer
418 static ssize_t debug_output(struct file *file, /* file descriptor */
419 char __user *user_buf, /* user buffer */
420 size_t len, /* length of buffer */
421 loff_t *offset) /* offset in the file */
423 size_t count = 0;
424 size_t entry_offset, size = 0;
425 file_private_info_t *p_info;
427 p_info = ((file_private_info_t *) file->private_data);
428 if (*offset != p_info->offset)
429 return -EPIPE;
430 if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
431 return 0;
433 entry_offset = p_info->act_entry_offset;
435 while(count < len){
436 size = debug_format_entry(p_info);
437 size = min((len - count), (size - entry_offset));
439 if(size){
440 if (copy_to_user(user_buf + count,
441 p_info->temp_buf + entry_offset, size))
442 return -EFAULT;
444 count += size;
445 entry_offset = 0;
446 if(count != len)
447 if(debug_next_entry(p_info))
448 goto out;
450 out:
451 p_info->offset = *offset + count;
452 p_info->act_entry_offset = size;
453 *offset = p_info->offset;
454 return count;
458 * debug_input:
459 * - called for user write()
460 * - calls input function of view
463 static ssize_t debug_input(struct file *file,
464 const char __user *user_buf, size_t length,
465 loff_t *offset)
467 int rc = 0;
468 file_private_info_t *p_info;
470 down(&debug_lock);
471 p_info = ((file_private_info_t *) file->private_data);
472 if (p_info->view->input_proc)
473 rc = p_info->view->input_proc(p_info->debug_info_org,
474 p_info->view, file, user_buf,
475 length, offset);
476 else
477 rc = -EPERM;
478 up(&debug_lock);
479 return rc; /* number of input characters */
483 * debug_open:
484 * - called for user open()
485 * - copies formated output to private_data area of the file
486 * handle
489 static int debug_open(struct inode *inode, struct file *file)
491 int i = 0, rc = 0;
492 file_private_info_t *p_info;
493 debug_info_t *debug_info, *debug_info_snapshot;
495 #ifdef DEBUG
496 printk("debug_open\n");
497 #endif
498 down(&debug_lock);
500 /* find debug log and view */
502 debug_info = debug_area_first;
503 while(debug_info != NULL){
504 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
505 if (debug_info->views[i] == NULL)
506 continue;
507 else if (debug_info->proc_entries[i] ==
508 PDE(file->f_dentry->d_inode)) {
509 goto found; /* found view ! */
512 debug_info = debug_info->next;
514 /* no entry found */
515 rc = -EINVAL;
516 goto out;
518 found:
520 /* make snapshot of current debug areas to get it consistent */
522 debug_info_snapshot = debug_info_copy(debug_info);
524 if(!debug_info_snapshot){
525 #ifdef DEBUG
526 printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
527 #endif
528 rc = -ENOMEM;
529 goto out;
532 if ((file->private_data =
533 kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
534 #ifdef DEBUG
535 printk(KERN_ERR "debug_open: kmalloc failed\n");
536 #endif
537 debug_info_free(debug_info_snapshot);
538 rc = -ENOMEM;
539 goto out;
541 p_info = (file_private_info_t *) file->private_data;
542 p_info->offset = 0;
543 p_info->debug_info_snap = debug_info_snapshot;
544 p_info->debug_info_org = debug_info;
545 p_info->view = debug_info->views[i];
546 p_info->act_area = 0;
547 p_info->act_entry = DEBUG_PROLOG_ENTRY;
548 p_info->act_entry_offset = 0;
550 debug_info_get(debug_info);
552 out:
553 up(&debug_lock);
554 return rc;
558 * debug_close:
559 * - called for user close()
560 * - deletes private_data area of the file handle
563 static int debug_close(struct inode *inode, struct file *file)
565 file_private_info_t *p_info;
566 #ifdef DEBUG
567 printk("debug_close\n");
568 #endif
569 p_info = (file_private_info_t *) file->private_data;
570 debug_info_free(p_info->debug_info_snap);
571 debug_info_put(p_info->debug_info_org);
572 kfree(file->private_data);
573 return 0; /* success */
577 * debug_register:
578 * - creates and initializes debug area for the caller
579 * - returns handle for debug area
582 debug_info_t *debug_register
583 (char *name, int page_order, int nr_areas, int buf_size)
585 debug_info_t *rc = NULL;
587 if (!initialized)
588 BUG();
589 down(&debug_lock);
591 /* create new debug_info */
593 rc = debug_info_create(name, page_order, nr_areas, buf_size);
594 if(!rc)
595 goto out;
596 debug_register_view(rc, &debug_level_view);
597 debug_register_view(rc, &debug_flush_view);
598 #ifdef DEBUG
599 printk(KERN_INFO
600 "debug: reserved %d areas of %d pages for debugging %s\n",
601 nr_areas, 1 << page_order, rc->name);
602 #endif
603 out:
604 if (rc == NULL){
605 printk(KERN_ERR "debug: debug_register failed for %s\n",name);
607 up(&debug_lock);
608 return rc;
612 * debug_unregister:
613 * - give back debug area
616 void debug_unregister(debug_info_t * id)
618 if (!id)
619 goto out;
620 down(&debug_lock);
621 #ifdef DEBUG
622 printk(KERN_INFO "debug: unregistering %s\n", id->name);
623 #endif
624 debug_info_put(id);
625 up(&debug_lock);
627 out:
628 return;
632 * debug_set_level:
633 * - set actual debug level
636 void debug_set_level(debug_info_t* id, int new_level)
638 unsigned long flags;
639 if(!id)
640 return;
641 spin_lock_irqsave(&id->lock,flags);
642 if(new_level == DEBUG_OFF_LEVEL){
643 id->level = DEBUG_OFF_LEVEL;
644 printk(KERN_INFO "debug: %s: switched off\n",id->name);
645 } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
646 printk(KERN_INFO
647 "debug: %s: level %i is out of range (%i - %i)\n",
648 id->name, new_level, 0, DEBUG_MAX_LEVEL);
649 } else {
650 id->level = new_level;
651 #ifdef DEBUG
652 printk(KERN_INFO
653 "debug: %s: new level %i\n",id->name,id->level);
654 #endif
656 spin_unlock_irqrestore(&id->lock,flags);
661 * proceed_active_entry:
662 * - set active entry to next in the ring buffer
665 extern inline void proceed_active_entry(debug_info_t * id)
667 if ((id->active_entry[id->active_area] += id->entry_size)
668 > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
669 id->active_entry[id->active_area] = 0;
673 * proceed_active_area:
674 * - set active area to next in the ring buffer
677 extern inline void proceed_active_area(debug_info_t * id)
679 id->active_area++;
680 id->active_area = id->active_area % id->nr_areas;
684 * get_active_entry:
687 extern inline debug_entry_t *get_active_entry(debug_info_t * id)
689 return (debug_entry_t *) ((char *) id->areas[id->active_area] +
690 id->active_entry[id->active_area]);
694 * debug_finish_entry:
695 * - set timestamp, caller address, cpu number etc.
698 extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active,
699 int level, int exception)
701 STCK(active->id.stck);
702 active->id.fields.cpuid = smp_processor_id();
703 active->caller = __builtin_return_address(0);
704 active->id.fields.exception = exception;
705 active->id.fields.level = level;
706 proceed_active_entry(id);
707 if(exception)
708 proceed_active_area(id);
712 * debug_event_common:
713 * - write debug entry with given size
716 debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
717 int len)
719 unsigned long flags;
720 debug_entry_t *active;
722 spin_lock_irqsave(&id->lock, flags);
723 active = get_active_entry(id);
724 memset(DEBUG_DATA(active), 0, id->buf_size);
725 memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
726 debug_finish_entry(id, active, level, 0);
727 spin_unlock_irqrestore(&id->lock, flags);
729 return active;
733 * debug_exception_common:
734 * - write debug entry with given size and switch to next debug area
737 debug_entry_t *debug_exception_common(debug_info_t * id, int level,
738 const void *buf, int len)
740 unsigned long flags;
741 debug_entry_t *active;
743 spin_lock_irqsave(&id->lock, flags);
744 active = get_active_entry(id);
745 memset(DEBUG_DATA(active), 0, id->buf_size);
746 memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
747 debug_finish_entry(id, active, level, 1);
748 spin_unlock_irqrestore(&id->lock, flags);
750 return active;
754 * counts arguments in format string for sprintf view
757 extern inline int debug_count_numargs(char *string)
759 int numargs=0;
761 while(*string) {
762 if(*string++=='%')
763 numargs++;
765 return(numargs);
769 * debug_sprintf_event:
772 debug_entry_t *debug_sprintf_event(debug_info_t* id,
773 int level,char *string,...)
775 va_list ap;
776 int numargs,idx;
777 unsigned long flags;
778 debug_sprintf_entry_t *curr_event;
779 debug_entry_t *active;
781 if((!id) || (level > id->level))
782 return NULL;
784 numargs=debug_count_numargs(string);
786 spin_lock_irqsave(&id->lock, flags);
787 active = get_active_entry(id);
788 curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
789 va_start(ap,string);
790 curr_event->string=string;
791 for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
792 curr_event->args[idx]=va_arg(ap,long);
793 va_end(ap);
794 debug_finish_entry(id, active, level, 0);
795 spin_unlock_irqrestore(&id->lock, flags);
797 return active;
801 * debug_sprintf_exception:
804 debug_entry_t *debug_sprintf_exception(debug_info_t* id,
805 int level,char *string,...)
807 va_list ap;
808 int numargs,idx;
809 unsigned long flags;
810 debug_sprintf_entry_t *curr_event;
811 debug_entry_t *active;
813 if((!id) || (level > id->level))
814 return NULL;
816 numargs=debug_count_numargs(string);
818 spin_lock_irqsave(&id->lock, flags);
819 active = get_active_entry(id);
820 curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
821 va_start(ap,string);
822 curr_event->string=string;
823 for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
824 curr_event->args[idx]=va_arg(ap,long);
825 va_end(ap);
826 debug_finish_entry(id, active, level, 1);
827 spin_unlock_irqrestore(&id->lock, flags);
829 return active;
833 * debug_init:
834 * - is called exactly once to initialize the debug feature
837 static int __init debug_init(void)
839 int rc = 0;
841 down(&debug_lock);
842 #ifdef CONFIG_PROC_FS
843 debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
844 #endif /* CONFIG_PROC_FS */
845 printk(KERN_INFO "debug: Initialization complete\n");
846 initialized = 1;
847 up(&debug_lock);
849 return rc;
853 * debug_register_view:
856 int debug_register_view(debug_info_t * id, struct debug_view *view)
858 int rc = 0;
859 int i;
860 unsigned long flags;
861 mode_t mode = S_IFREG;
862 struct proc_dir_entry *pde;
864 if (!id)
865 goto out;
866 pde = create_proc_entry(view->name, mode, id->proc_root_entry);
867 if (!pde){
868 printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name);
869 rc = -1;
870 goto out;
873 spin_lock_irqsave(&id->lock, flags);
874 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
875 if (id->views[i] == NULL)
876 break;
878 if (i == DEBUG_MAX_VIEWS) {
879 printk(KERN_WARNING "debug: cannot register view %s/%s\n",
880 id->name,view->name);
881 printk(KERN_WARNING
882 "debug: maximum number of views reached (%i)!\n", i);
883 remove_proc_entry(pde->name, id->proc_root_entry);
884 rc = -1;
886 else {
887 id->views[i] = view;
888 if (view->prolog_proc || view->format_proc || view->header_proc)
889 mode |= S_IRUSR;
890 if (view->input_proc)
891 mode |= S_IWUSR;
892 pde->proc_fops = &debug_file_ops;
893 id->proc_entries[i] = pde;
895 spin_unlock_irqrestore(&id->lock, flags);
896 out:
897 return rc;
901 * debug_unregister_view:
904 int debug_unregister_view(debug_info_t * id, struct debug_view *view)
906 int rc = 0;
907 int i;
908 unsigned long flags;
910 if (!id)
911 goto out;
912 spin_lock_irqsave(&id->lock, flags);
913 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
914 if (id->views[i] == view)
915 break;
917 if (i == DEBUG_MAX_VIEWS)
918 rc = -1;
919 else {
920 #ifdef CONFIG_PROC_FS
921 remove_proc_entry(id->proc_entries[i]->name,
922 id->proc_root_entry);
923 #endif
924 id->views[i] = NULL;
925 rc = 0;
927 spin_unlock_irqrestore(&id->lock, flags);
928 out:
929 return rc;
933 * functions for debug-views
934 ***********************************
938 * prints out actual debug level
941 static int debug_prolog_level_fn(debug_info_t * id,
942 struct debug_view *view, char *out_buf)
944 int rc = 0;
946 if(id->level == -1) rc = sprintf(out_buf,"-\n");
947 else rc = sprintf(out_buf, "%i\n", id->level);
948 return rc;
952 * reads new debug level
955 static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
956 struct file *file, const char __user *user_buf,
957 size_t in_buf_size, loff_t * offset)
959 char input_buf[1];
960 int rc = in_buf_size;
962 if (*offset != 0)
963 goto out;
964 if (copy_from_user(input_buf, user_buf, 1)){
965 rc = -EFAULT;
966 goto out;
968 if (isdigit(input_buf[0])) {
969 int new_level = ((int) input_buf[0] - (int) '0');
970 debug_set_level(id, new_level);
971 } else if(input_buf[0] == '-') {
972 debug_set_level(id, DEBUG_OFF_LEVEL);
973 } else {
974 printk(KERN_INFO "debug: level `%c` is not valid\n",
975 input_buf[0]);
977 out:
978 *offset += in_buf_size;
979 return rc; /* number of input characters */
984 * flushes debug areas
987 void debug_flush(debug_info_t* id, int area)
989 unsigned long flags;
990 int i;
992 if(!id)
993 return;
994 spin_lock_irqsave(&id->lock,flags);
995 if(area == DEBUG_FLUSH_ALL){
996 id->active_area = 0;
997 memset(id->active_entry, 0, id->nr_areas * sizeof(int));
998 for (i = 0; i < id->nr_areas; i++)
999 memset(id->areas[i], 0, PAGE_SIZE << id->page_order);
1000 printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
1001 } else if(area >= 0 && area < id->nr_areas) {
1002 id->active_entry[area] = 0;
1003 memset(id->areas[area], 0, PAGE_SIZE << id->page_order);
1004 printk(KERN_INFO
1005 "debug: %s: area %i has been flushed\n",
1006 id->name, area);
1007 } else {
1008 printk(KERN_INFO
1009 "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
1010 id->name, area, 0, id->nr_areas-1);
1012 spin_unlock_irqrestore(&id->lock,flags);
1016 * view function: flushes debug areas
1019 static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1020 struct file *file, const char __user *user_buf,
1021 size_t in_buf_size, loff_t * offset)
1023 char input_buf[1];
1024 int rc = in_buf_size;
1026 if (*offset != 0)
1027 goto out;
1028 if (copy_from_user(input_buf, user_buf, 1)){
1029 rc = -EFAULT;
1030 goto out;
1032 if(input_buf[0] == '-') {
1033 debug_flush(id, DEBUG_FLUSH_ALL);
1034 goto out;
1036 if (isdigit(input_buf[0])) {
1037 int area = ((int) input_buf[0] - (int) '0');
1038 debug_flush(id, area);
1039 goto out;
1042 printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
1044 out:
1045 *offset += in_buf_size;
1046 return rc; /* number of input characters */
1050 * prints debug header in raw format
1053 int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1054 int area, debug_entry_t * entry, char *out_buf)
1056 int rc;
1058 rc = sizeof(debug_entry_t);
1059 memcpy(out_buf,entry,sizeof(debug_entry_t));
1060 return rc;
1064 * prints debug data in raw format
1067 static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1068 char *out_buf, const char *in_buf)
1070 int rc;
1072 rc = id->buf_size;
1073 memcpy(out_buf, in_buf, id->buf_size);
1074 return rc;
1078 * prints debug data in hex/ascii format
1081 static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1082 char *out_buf, const char *in_buf)
1084 int i, rc = 0;
1086 for (i = 0; i < id->buf_size; i++) {
1087 rc += sprintf(out_buf + rc, "%02x ",
1088 ((unsigned char *) in_buf)[i]);
1090 rc += sprintf(out_buf + rc, "| ");
1091 for (i = 0; i < id->buf_size; i++) {
1092 unsigned char c = in_buf[i];
1093 if (!isprint(c))
1094 rc += sprintf(out_buf + rc, ".");
1095 else
1096 rc += sprintf(out_buf + rc, "%c", c);
1098 rc += sprintf(out_buf + rc, "\n");
1099 return rc;
1103 * prints header for debug entry
1106 int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1107 int area, debug_entry_t * entry, char *out_buf)
1109 struct timeval time_val;
1110 unsigned long long time;
1111 char *except_str;
1112 unsigned long caller;
1113 int rc = 0;
1114 unsigned int level;
1116 level = entry->id.fields.level;
1117 time = entry->id.stck;
1118 /* adjust todclock to 1970 */
1119 time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
1120 tod_to_timeval(time, &time_val);
1122 if (entry->id.fields.exception)
1123 except_str = "*";
1124 else
1125 except_str = "-";
1126 caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN;
1127 rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p ",
1128 area, time_val.tv_sec, time_val.tv_usec, level,
1129 except_str, entry->id.fields.cpuid, (void *) caller);
1130 return rc;
1134 * prints debug data sprintf-formated:
1135 * debug_sprinf_event/exception calls must be used together with this view
1138 #define DEBUG_SPRINTF_MAX_ARGS 10
1140 int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
1141 char *out_buf, debug_sprintf_entry_t *curr_event)
1143 int num_longs, num_used_args = 0,i, rc = 0;
1144 int index[DEBUG_SPRINTF_MAX_ARGS];
1146 /* count of longs fit into one entry */
1147 num_longs = id->buf_size / sizeof(long);
1149 if(num_longs < 1)
1150 goto out; /* bufsize of entry too small */
1151 if(num_longs == 1) {
1152 /* no args, we use only the string */
1153 strcpy(out_buf, curr_event->string);
1154 rc = strlen(curr_event->string);
1155 goto out;
1158 /* number of arguments used for sprintf (without the format string) */
1159 num_used_args = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
1161 memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
1163 for(i = 0; i < num_used_args; i++)
1164 index[i] = i;
1166 rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
1167 curr_event->args[index[1]], curr_event->args[index[2]],
1168 curr_event->args[index[3]], curr_event->args[index[4]],
1169 curr_event->args[index[5]], curr_event->args[index[6]],
1170 curr_event->args[index[7]], curr_event->args[index[8]],
1171 curr_event->args[index[9]]);
1173 out:
1175 return rc;
1179 * clean up module
1181 void __exit debug_exit(void)
1183 #ifdef DEBUG
1184 printk("debug_cleanup_module: \n");
1185 #endif
1186 #ifdef CONFIG_PROC_FS
1187 remove_proc_entry(debug_proc_root_entry->name, NULL);
1188 #endif /* CONFIG_PROC_FS */
1189 return;
1193 * module definitions
1195 core_initcall(debug_init);
1196 module_exit(debug_exit);
1197 MODULE_LICENSE("GPL");
1199 EXPORT_SYMBOL(debug_register);
1200 EXPORT_SYMBOL(debug_unregister);
1201 EXPORT_SYMBOL(debug_set_level);
1202 EXPORT_SYMBOL(debug_register_view);
1203 EXPORT_SYMBOL(debug_unregister_view);
1204 EXPORT_SYMBOL(debug_event_common);
1205 EXPORT_SYMBOL(debug_exception_common);
1206 EXPORT_SYMBOL(debug_hex_ascii_view);
1207 EXPORT_SYMBOL(debug_raw_view);
1208 EXPORT_SYMBOL(debug_dflt_header_fn);
1209 EXPORT_SYMBOL(debug_sprintf_view);
1210 EXPORT_SYMBOL(debug_sprintf_exception);
1211 EXPORT_SYMBOL(debug_sprintf_event);