File: /usr/src/linux/arch/s390/kernel/debug.c
1 /*
2 * arch/s390/kernel/debug.c
3 * S/390 debug facility
4 *
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)
9 *
10 * Bugreports to: <Linux390@de.ibm.com>
11 */
12
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 <linux/version.h>
20 #include <asm/uaccess.h>
21 #include <asm/semaphore.h>
22
23 #include <linux/module.h>
24
25 #include <asm/debug.h>
26
27 #define MIN(a,b) (((a)<(b))?(a):(b))
28 #define DEBUG_PROLOG_ENTRY -1
29
30 /* typedefs */
31
32 typedef struct file_private_info {
33 loff_t offset; /* offset of last read in file */
34 int act_area; /* number of last formated area */
35 int act_entry; /* last formated entry (offset */
36 /* relative to beginning of last */
37 /* formated area) */
38 size_t act_entry_offset; /* up to this offset we copied */
39 /* in last read the last formated */
40 /* entry to userland */
41 char temp_buf[2048]; /* buffer for output */
42 debug_info_t *debug_info_org; /* original debug information */
43 debug_info_t *debug_info_snap; /* snapshot of debug information */
44 struct debug_view *view; /* used view of debug info */
45 } file_private_info_t;
46
47 typedef struct
48 {
49 char *string;
50 /*
51 * This assumes that all args are converted into longs
52 * on L/390 this is the case for all types of parameter
53 * except of floats, and long long (32 bit)
54 *
55 */
56 long args[0];
57 } debug_sprintf_entry;
58
59
60 extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
61
62 /* internal function prototyes */
63
64 static int debug_init(void);
65 static ssize_t debug_output(struct file *file, char *user_buf,
66 size_t user_len, loff_t * offset);
67 static ssize_t debug_input(struct file *file, const char *user_buf,
68 size_t user_len, loff_t * offset);
69 static int debug_open(struct inode *inode, struct file *file);
70 static int debug_close(struct inode *inode, struct file *file);
71 static struct proc_dir_entry
72 *debug_create_proc_dir_entry(struct proc_dir_entry *root,
73 const char *name, mode_t mode,
74 struct inode_operations *iops,
75 struct file_operations *fops);
76 static void debug_delete_proc_dir_entry(struct proc_dir_entry *root,
77 struct proc_dir_entry *entry);
78 static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
79 static void debug_info_get(debug_info_t *);
80 static void debug_info_put(debug_info_t *);
81 static int debug_prolog_level_fn(debug_info_t * id,
82 struct debug_view *view, char *out_buf);
83 static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
84 struct file *file, const char *user_buf,
85 size_t user_buf_size, loff_t * offset);
86 static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
87 char *out_buf, const char *in_buf);
88 static int debug_raw_format_fn(debug_info_t * id,
89 struct debug_view *view, char *out_buf,
90 const char *in_buf);
91 static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
92 int area, debug_entry_t * entry, char *out_buf);
93
94 static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
95 char *out_buf, debug_sprintf_entry *curr_event);
96
97 /* globals */
98
99 struct debug_view debug_raw_view = {
100 "raw",
101 NULL,
102 &debug_raw_header_fn,
103 &debug_raw_format_fn,
104 NULL,
105 NULL
106 };
107
108 struct debug_view debug_hex_ascii_view = {
109 "hex_ascii",
110 NULL,
111 &debug_dflt_header_fn,
112 &debug_hex_ascii_format_fn,
113 NULL,
114 NULL
115 };
116
117 struct debug_view debug_level_view = {
118 "level",
119 &debug_prolog_level_fn,
120 NULL,
121 NULL,
122 &debug_input_level_fn,
123 NULL
124 };
125
126 struct debug_view debug_sprintf_view = {
127 "sprintf",
128 NULL,
129 &debug_dflt_header_fn,
130 (debug_format_proc_t*)&debug_sprintf_format_fn,
131 NULL,
132 NULL
133 };
134
135
136 unsigned int debug_feature_version = __DEBUG_FEATURE_VERSION;
137
138 /* static globals */
139
140 static debug_info_t *debug_area_first = NULL;
141 static debug_info_t *debug_area_last = NULL;
142 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
143 static struct semaphore debug_lock = MUTEX;
144 #else
145 DECLARE_MUTEX(debug_lock);
146 #endif
147
148 static int initialized = 0;
149
150 static struct file_operations debug_file_ops = {
151 read: debug_output,
152 write: debug_input,
153 open: debug_open,
154 release: debug_close,
155 };
156
157 static struct inode_operations debug_inode_ops = {
158 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
159 default_file_ops: &debug_file_ops, /* file ops */
160 #endif
161 };
162
163
164 static struct proc_dir_entry *debug_proc_root_entry;
165
166 /* functions */
167
168 /*
169 * debug_info_alloc
170 * - alloc new debug-info
171 */
172
173 static debug_info_t* debug_info_alloc(char *name, int page_order,
174 int nr_areas, int buf_size)
175 {
176 debug_info_t* rc;
177 int i;
178
179 /* alloc everything */
180
181 rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
182 if(!rc)
183 goto fail_malloc_rc;
184 rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
185 if(!rc->active_entry)
186 goto fail_malloc_active_entry;
187 memset(rc->active_entry, 0, nr_areas * sizeof(int));
188 rc->areas = (debug_entry_t **) kmalloc(nr_areas *
189 sizeof(debug_entry_t *),
190 GFP_ATOMIC);
191 if (!rc->areas)
192 goto fail_malloc_areas;
193 for (i = 0; i < nr_areas; i++) {
194 rc->areas[i] = (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
195 page_order);
196 if (!rc->areas[i]) {
197 for (i--; i >= 0; i--) {
198 free_pages((unsigned long) rc->areas[i],
199 page_order);
200 }
201 goto fail_malloc_areas2;
202 } else {
203 memset(rc->areas[i], 0, PAGE_SIZE << page_order);
204 }
205 }
206
207 /* initialize members */
208
209 spin_lock_init(&rc->lock);
210 rc->page_order = page_order;
211 rc->nr_areas = nr_areas;
212 rc->active_area = 0;
213 rc->level = DEBUG_DEFAULT_LEVEL;
214 rc->buf_size = buf_size;
215 rc->entry_size = sizeof(debug_entry_t) + buf_size;
216 strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1)));
217 rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0;
218 memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
219 memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
220 sizeof(struct proc_dir_entry*));
221 atomic_set(&(rc->ref_count), 0);
222
223 return rc;
224
225 fail_malloc_areas2:
226 kfree(rc->areas);
227 fail_malloc_areas:
228 kfree(rc->active_entry);
229 fail_malloc_active_entry:
230 kfree(rc);
231 fail_malloc_rc:
232 return NULL;
233 }
234
235 /*
236 * debug_info_free
237 * - free memory debug-info
238 */
239
240 static void debug_info_free(debug_info_t* db_info){
241 int i;
242 for (i = 0; i < db_info->nr_areas; i++) {
243 free_pages((unsigned long) db_info->areas[i],
244 db_info->page_order);
245 }
246 kfree(db_info->areas);
247 kfree(db_info->active_entry);
248 kfree(db_info);
249 }
250
251 /*
252 * debug_info_create
253 * - create new debug-info
254 */
255
256 static debug_info_t* debug_info_create(char *name, int page_order,
257 int nr_areas, int buf_size)
258 {
259 debug_info_t* rc;
260
261 rc = debug_info_alloc(name, page_order, nr_areas, buf_size);
262 if(!rc)
263 goto out;
264
265
266 /* create proc rood directory */
267
268 rc->proc_root_entry =
269 debug_create_proc_dir_entry(debug_proc_root_entry, rc->name,
270 S_IFDIR | S_IRUGO | S_IXUGO |
271 S_IWUSR | S_IWGRP, NULL, NULL);
272
273 /* append new element to linked list */
274
275 if(debug_area_first == NULL){
276 /* first element in list */
277 debug_area_first = rc;
278 rc->prev = NULL;
279 }
280 else{
281 /* append element to end of list */
282 debug_area_last->next = rc;
283 rc->prev = debug_area_last;
284 }
285 debug_area_last = rc;
286 rc->next = NULL;
287
288 debug_info_get(rc);
289 out:
290 return rc;
291 }
292
293 /*
294 * debug_info_copy
295 * - copy debug-info
296 */
297
298 static debug_info_t* debug_info_copy(debug_info_t* in)
299 {
300 int i;
301 debug_info_t* rc;
302 rc = debug_info_alloc(in->name, in->page_order,
303 in->nr_areas, in->buf_size);
304 if(!rc)
305 goto out;
306
307 for(i = 0; i < in->nr_areas; i++){
308 memcpy(rc->areas[i],in->areas[i], PAGE_SIZE << in->page_order);
309 }
310 out:
311 return rc;
312 }
313
314 /*
315 * debug_info_get
316 * - increments reference count for debug-info
317 */
318
319 static void debug_info_get(debug_info_t * db_info)
320 {
321 if (db_info)
322 atomic_inc(&db_info->ref_count);
323 }
324
325 /*
326 * debug_info_put:
327 * - decreases reference count for debug-info and frees it if necessary
328 */
329
330 static void debug_info_put(debug_info_t *db_info)
331 {
332 int i;
333
334 if (!db_info)
335 return;
336 if (atomic_dec_and_test(&db_info->ref_count)) {
337 printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
338 db_info, db_info->name);
339 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
340 if (db_info->views[i] != NULL)
341 debug_delete_proc_dir_entry
342 (db_info->proc_root_entry,
343 db_info->proc_entries[i]);
344 }
345 debug_delete_proc_dir_entry(debug_proc_root_entry,
346 db_info->proc_root_entry);
347 if(db_info == debug_area_first)
348 debug_area_first = db_info->next;
349 if(db_info == debug_area_last)
350 debug_area_last = db_info->prev;
351 if(db_info->prev) db_info->prev->next = db_info->next;
352 if(db_info->next) db_info->next->prev = db_info->prev;
353 debug_info_free(db_info);
354 }
355 }
356
357 /*
358 * debug_format_entry:
359 * - format one debug entry and return size of formated data
360 */
361
362 static int debug_format_entry(file_private_info_t *p_info)
363 {
364 debug_info_t *id_org = p_info->debug_info_org;
365 debug_info_t *id_snap = p_info->debug_info_snap;
366 struct debug_view *view = p_info->view;
367 debug_entry_t *act_entry;
368 size_t len = 0;
369 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
370 /* print prolog */
371 if (view->prolog_proc)
372 len += view->prolog_proc(id_org, view,p_info->temp_buf);
373 goto out;
374 }
375
376 act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area] +
377 p_info->act_entry);
378
379 if (act_entry->id.stck == 0LL)
380 goto out; /* empty entry */
381 if (view->header_proc)
382 len += view->header_proc(id_org, view, p_info->act_area,
383 act_entry, p_info->temp_buf + len);
384 if (view->format_proc)
385 len += view->format_proc(id_org, view, p_info->temp_buf + len,
386 DEBUG_DATA(act_entry));
387 out:
388 return len;
389 }
390
391 /*
392 * debug_next_entry:
393 * - goto next entry in p_info
394 */
395
396 extern inline int debug_next_entry(file_private_info_t *p_info)
397 {
398 debug_info_t *id = p_info->debug_info_snap;
399 if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
400 p_info->act_entry = 0;
401 goto out;
402 }
403 if ((p_info->act_entry += id->entry_size)
404 > ((PAGE_SIZE << (id->page_order))
405 - id->entry_size)){
406
407 /* next area */
408 p_info->act_entry = 0;
409 p_info->act_area++;
410 if(p_info->act_area >= id->nr_areas)
411 return 1;
412 }
413 out:
414 return 0;
415 }
416
417 /*
418 * debug_output:
419 * - called for user read()
420 * - copies formated debug entries to the user buffer
421 */
422
423 static ssize_t debug_output(struct file *file, /* file descriptor */
424 char *user_buf, /* user buffer */
425 size_t len, /* length of buffer */
426 loff_t *offset /* offset in the file */ )
427 {
428 size_t count = 0;
429 size_t entry_offset, size = 0;
430 int rc;
431 file_private_info_t *p_info;
432
433 p_info = ((file_private_info_t *) file->private_data);
434 if (*offset != p_info->offset)
435 return -EPIPE;
436 if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
437 return 0;
438
439 entry_offset = p_info->act_entry_offset;
440
441 while(count < len){
442 size = debug_format_entry(p_info);
443 size = MIN((len - count), (size - entry_offset));
444
445 if(size){
446 if ((rc = copy_to_user(user_buf + count,
447 p_info->temp_buf + entry_offset, size)))
448 return rc;
449 }
450 count += size;
451 entry_offset = 0;
452 if(count != len)
453 if(debug_next_entry(p_info))
454 goto out;
455 }
456 out:
457 p_info->offset = *offset + count;
458 p_info->act_entry_offset = size;
459 *offset = p_info->offset;
460 return count;
461 }
462
463 /*
464 * debug_input:
465 * - called for user write()
466 * - calls input function of view
467 */
468
469 static ssize_t debug_input(struct file *file,
470 const char *user_buf, size_t length,
471 loff_t *offset)
472 {
473 int rc = 0;
474 file_private_info_t *p_info;
475
476 down(&debug_lock);
477 p_info = ((file_private_info_t *) file->private_data);
478 if (p_info->view->input_proc)
479 rc = p_info->view->input_proc(p_info->debug_info_org,
480 p_info->view, file, user_buf,
481 length, offset);
482 else
483 rc = -EPERM;
484 up(&debug_lock);
485 return rc; /* number of input characters */
486 }
487
488 /*
489 * debug_open:
490 * - called for user open()
491 * - copies formated output to private_data area of the file
492 * handle
493 */
494
495 static int debug_open(struct inode *inode, struct file *file)
496 {
497 int i = 0, rc = 0;
498 file_private_info_t *p_info;
499 debug_info_t *debug_info, *debug_info_snapshot;
500
501 #ifdef DEBUG
502 printk("debug_open\n");
503 #endif
504 MOD_INC_USE_COUNT;
505 down(&debug_lock);
506
507 /* find debug log and view */
508
509 debug_info = debug_area_first;
510 while(debug_info != NULL){
511 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
512 if (debug_info->views[i] == NULL)
513 continue;
514 else if (debug_info->proc_entries[i]->low_ino ==
515 file->f_dentry->d_inode->i_ino) {
516 goto found; /* found view ! */
517 }
518 }
519 debug_info = debug_info->next;
520 }
521 /* no entry found */
522 rc = -EINVAL;
523 goto out;
524
525 found:
526
527 /* make snapshot of current debug areas to get it consistent */
528
529 debug_info_snapshot = debug_info_copy(debug_info);
530
531 if(!debug_info_snapshot){
532 printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
533 rc = -ENOMEM;
534 goto out;
535 }
536
537 if ((file->private_data =
538 kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
539 printk(KERN_ERR "debug_open: kmalloc failed\n");
540 debug_info_free(debug_info_snapshot);
541 rc = -ENOMEM;
542 goto out;
543 }
544 p_info = (file_private_info_t *) file->private_data;
545 p_info->offset = 0;
546 p_info->debug_info_snap = debug_info_snapshot;
547 p_info->debug_info_org = debug_info;
548 p_info->view = debug_info->views[i];
549 p_info->act_area = 0;
550 p_info->act_entry = DEBUG_PROLOG_ENTRY;
551 p_info->act_entry_offset = 0;
552
553 debug_info_get(debug_info);
554
555 out:
556 up(&debug_lock);
557 if (rc != 0)
558 MOD_DEC_USE_COUNT;
559 return rc;
560 }
561
562 /*
563 * debug_close:
564 * - called for user close()
565 * - deletes private_data area of the file handle
566 */
567
568 static int debug_close(struct inode *inode, struct file *file)
569 {
570 file_private_info_t *p_info;
571 #ifdef DEBUG
572 printk("debug_close\n");
573 #endif
574 p_info = (file_private_info_t *) file->private_data;
575 debug_info_free(p_info->debug_info_snap);
576 debug_info_put(p_info->debug_info_org);
577 kfree(file->private_data);
578 MOD_DEC_USE_COUNT;
579 return 0; /* success */
580 }
581
582 /*
583 * debug_create_proc_dir_entry:
584 * - initializes proc-dir-entry and registers it
585 */
586
587 static struct proc_dir_entry *debug_create_proc_dir_entry
588 (struct proc_dir_entry *root, const char *name, mode_t mode,
589 struct inode_operations *iops, struct file_operations *fops)
590 {
591 struct proc_dir_entry *rc = NULL;
592
593 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
594 const char *fn = name;
595 int len;
596 len = strlen(fn);
597
598 rc = (struct proc_dir_entry *) kmalloc(sizeof(struct proc_dir_entry)
599 + len + 1, GFP_ATOMIC);
600 if (!rc)
601 goto out;
602
603 memset(rc, 0, sizeof(struct proc_dir_entry));
604 memcpy(((char *) rc) + sizeof(*rc), fn, len + 1);
605 rc->name = ((char *) rc) + sizeof(*rc);
606 rc->namelen = len;
607 rc->low_ino = 0, rc->mode = mode;
608 rc->nlink = 1;
609 rc->uid = 0;
610 rc->gid = 0;
611 rc->size = 0;
612 rc->get_info = NULL;
613 rc->ops = iops;
614
615 proc_register(root, rc);
616 #else
617 rc = create_proc_entry(name, mode, root);
618 if (!rc)
619 goto out;
620 if (fops)
621 rc->proc_fops = fops;
622 #endif
623
624 out:
625 return rc;
626 }
627
628
629 /*
630 * delete_proc_dir_entry:
631 */
632
633 static void debug_delete_proc_dir_entry
634 (struct proc_dir_entry *root, struct proc_dir_entry *proc_entry)
635 {
636
637 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
638 proc_unregister(root, proc_entry->low_ino);
639 kfree(proc_entry);
640 #else
641 remove_proc_entry(proc_entry->name, root);
642 #endif
643 }
644
645 /*
646 * debug_register:
647 * - creates and initializes debug area for the caller
648 * - returns handle for debug area
649 */
650
651 debug_info_t *debug_register
652 (char *name, int page_order, int nr_areas, int buf_size)
653 {
654 debug_info_t *rc = NULL;
655
656 MOD_INC_USE_COUNT;
657 if (!initialized)
658 debug_init();
659 down(&debug_lock);
660
661 /* create new debug_info */
662
663 rc = debug_info_create(name, page_order, nr_areas, buf_size);
664 if(!rc)
665 goto out;
666 debug_register_view(rc, &debug_level_view);
667 printk(KERN_INFO
668 "debug: reserved %d areas of %d pages for debugging %s\n",
669 nr_areas, 1 << page_order, rc->name);
670 out:
671 if (rc == NULL){
672 printk(KERN_ERR "debug: debug_register failed for %s\n",name);
673 MOD_DEC_USE_COUNT;
674 }
675 up(&debug_lock);
676 return rc;
677 }
678
679 /*
680 * debug_unregister:
681 * - give back debug area
682 */
683
684 void debug_unregister(debug_info_t * id)
685 {
686 if (!id)
687 goto out;
688 down(&debug_lock);
689 printk(KERN_INFO "debug: unregistering %s\n", id->name);
690 debug_info_put(id);
691 up(&debug_lock);
692
693 MOD_DEC_USE_COUNT;
694 out:
695 return;
696 }
697
698 /*
699 * debug_set_level:
700 * - set actual debug level
701 */
702
703 void debug_set_level(debug_info_t* id, int new_level)
704 {
705 unsigned long flags;
706 if(!id)
707 return;
708 spin_lock_irqsave(&id->lock,flags);
709 if(new_level == DEBUG_OFF_LEVEL){
710 id->level = DEBUG_OFF_LEVEL;
711 printk(KERN_INFO "debug: %s: switched off\n",id->name);
712 } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
713 printk(KERN_INFO
714 "debug: %s: level %i is out of range (%i - %i)\n",
715 id->name, new_level, 0, DEBUG_MAX_LEVEL);
716 } else {
717 id->level = new_level;
718 printk(KERN_INFO
719 "debug: %s: new level %i\n",id->name,id->level);
720 }
721 spin_unlock_irqrestore(&id->lock,flags);
722 }
723
724
725 /*
726 * proceed_active_entry:
727 * - set active entry to next in the ring buffer
728 */
729
730 extern inline void proceed_active_entry(debug_info_t * id)
731 {
732 if ((id->active_entry[id->active_area] += id->entry_size)
733 > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
734 id->active_entry[id->active_area] = 0;
735 }
736
737 /*
738 * proceed_active_area:
739 * - set active area to next in the ring buffer
740 */
741
742 extern inline void proceed_active_area(debug_info_t * id)
743 {
744 id->active_area++;
745 id->active_area = id->active_area % id->nr_areas;
746 }
747
748 /*
749 * get_active_entry:
750 */
751
752 extern inline debug_entry_t *get_active_entry(debug_info_t * id)
753 {
754 return (debug_entry_t *) ((char *) id->areas[id->active_area] +
755 id->active_entry[id->active_area]);
756 }
757
758 /*
759 * debug_common:
760 * - set timestamp, caller address, cpu number etc.
761 */
762
763 extern inline debug_entry_t *debug_common(debug_info_t * id, int level,
764 const void *buf, int len, int exception)
765 {
766 unsigned long flags;
767 debug_entry_t *active;
768
769 spin_lock_irqsave(&id->lock, flags);
770 active = get_active_entry(id);
771 STCK(active->id.stck);
772 active->id.fields.cpuid = smp_processor_id();
773 active->caller = __builtin_return_address(0);
774 active->id.fields.exception = exception;
775 active->id.fields.level = level;
776 memset(DEBUG_DATA(active), 0, id->buf_size);
777 memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
778 proceed_active_entry(id);
779 if(exception)
780 proceed_active_area(id);
781 spin_unlock_irqrestore(&id->lock, flags);
782
783 return active;
784 }
785
786 /*
787 * debug_event_common:
788 * - write debug entry with given size
789 */
790
791 debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
792 int len)
793 {
794 return debug_common(id, level, buf, len, 0);
795 }
796
797 /*
798 * debug_exception_common:
799 * - write debug entry with given size and switch to next debug area
800 */
801
802 debug_entry_t *debug_exception_common(debug_info_t * id, int level,
803 const void *buf, int len)
804 {
805 return debug_common(id, level, buf, len, 1);
806 }
807
808 /*
809 * counts arguments in format string for sprintf view
810 */
811
812 extern inline int debug_count_numargs(char *string)
813 {
814 int numargs=0;
815
816 while(*string) {
817 if(*string++=='%')
818 numargs++;
819 }
820 return(numargs);
821 }
822
823 /*
824 * debug_sprintf_event:
825 */
826
827 debug_entry_t *debug_sprintf_event(debug_info_t* id,
828 int level,char *string,...)
829 {
830 va_list ap;
831 int numargs,alloc_size,idx;
832 debug_sprintf_entry *curr_event;
833 debug_entry_t *retval = NULL;
834
835 if((!id) || (level > id->level))
836 return NULL;
837 else {
838 numargs=debug_count_numargs(string);
839 alloc_size=offsetof(debug_sprintf_entry,args[numargs]);
840 curr_event=alloca(alloc_size);
841
842 if(curr_event){
843 va_start(ap,string);
844 curr_event->string=string;
845 for(idx=0;idx<numargs;idx++)
846 curr_event->args[idx]=va_arg(ap,long);
847 retval=debug_common(id,level, curr_event,alloc_size,0);
848 va_end(ap);
849 }
850 return retval;
851 }
852 }
853
854 /*
855 * debug_sprintf_exception:
856 */
857
858 debug_entry_t *debug_sprintf_exception(debug_info_t* id,
859 int level,char *string,...)
860 {
861 va_list ap;
862 int numargs,alloc_size,idx;
863 debug_sprintf_entry *curr_event;
864 debug_entry_t *retval = NULL;
865
866 if((!id) || (level > id->level))
867 return NULL;
868 else {
869 numargs=debug_count_numargs(string);
870 alloc_size=offsetof(debug_sprintf_entry,args[numargs]);
871 curr_event=alloca(alloc_size);
872
873 if(curr_event){
874 va_start(ap,string);
875 curr_event->string=string;
876 for(idx=0;idx<numargs;idx++)
877 curr_event->args[idx]=va_arg(ap,long);
878 retval=debug_common(id,level, curr_event,alloc_size,1);
879 va_end(ap);
880 }
881 return retval;
882 }
883 }
884
885 /*
886 * debug_init:
887 * - is called exactly once to initialize the debug feature
888 */
889
890 int debug_init(void)
891 {
892 int rc = 0;
893
894 down(&debug_lock);
895 if (!initialized) {
896 debug_proc_root_entry =
897 debug_create_proc_dir_entry(&proc_root, DEBUG_DIR_ROOT,
898 S_IFDIR | S_IRUGO | S_IXUGO
899 | S_IWUSR | S_IWGRP, NULL,
900 NULL);
901 printk(KERN_INFO "debug: Initialization complete\n");
902 initialized = 1;
903 }
904 up(&debug_lock);
905
906 return rc;
907 }
908
909 /*
910 * debug_register_view:
911 */
912
913 int debug_register_view(debug_info_t * id, struct debug_view *view)
914 {
915 int rc = 0;
916 int i;
917 unsigned long flags;
918 mode_t mode = S_IFREG;
919
920 if (!id)
921 goto out;
922 spin_lock_irqsave(&id->lock, flags);
923 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
924 if (id->views[i] == NULL)
925 break;
926 }
927 if (i == DEBUG_MAX_VIEWS) {
928 printk(KERN_WARNING "debug: cannot register view %s/%s\n",
929 id->name,view->name);
930 printk(KERN_WARNING
931 "debug: maximum number of views reached (%i)!\n", i);
932 rc = -1;
933 }
934 else {
935 id->views[i] = view;
936 if (view->prolog_proc || view->format_proc || view->header_proc)
937 mode |= S_IRUSR;
938 if (view->input_proc)
939 mode |= S_IWUSR;
940 id->proc_entries[i] =
941 debug_create_proc_dir_entry(id->proc_root_entry,
942 view->name, mode,
943 &debug_inode_ops,
944 &debug_file_ops);
945 rc = 0;
946 }
947 spin_unlock_irqrestore(&id->lock, flags);
948 out:
949 return rc;
950 }
951
952 /*
953 * debug_unregister_view:
954 */
955
956 int debug_unregister_view(debug_info_t * id, struct debug_view *view)
957 {
958 int rc = 0;
959 int i;
960 unsigned long flags;
961
962 if (!id)
963 goto out;
964 spin_lock_irqsave(&id->lock, flags);
965 for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
966 if (id->views[i] == view)
967 break;
968 }
969 if (i == DEBUG_MAX_VIEWS)
970 rc = -1;
971 else {
972 debug_delete_proc_dir_entry(id->proc_root_entry,
973 id->proc_entries[i]);
974 id->views[i] = NULL;
975 rc = 0;
976 }
977 spin_unlock_irqrestore(&id->lock, flags);
978 out:
979 return rc;
980 }
981
982 /*
983 * functions for debug-views
984 ***********************************
985 */
986
987 /*
988 * prints out actual debug level
989 */
990
991 static int debug_prolog_level_fn(debug_info_t * id,
992 struct debug_view *view, char *out_buf)
993 {
994 int rc = 0;
995
996 if(id->level == -1) rc = sprintf(out_buf,"-\n");
997 else rc = sprintf(out_buf, "%i\n", id->level);
998 return rc;
999 }
1000
1001 /*
1002 * reads new debug level
1003 */
1004
1005 static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
1006 struct file *file, const char *user_buf,
1007 size_t in_buf_size, loff_t * offset)
1008 {
1009 char input_buf[1];
1010 int rc = in_buf_size;
1011
1012 if (*offset != 0)
1013 goto out;
1014 if (copy_from_user(input_buf, user_buf, 1)){
1015 rc = -EFAULT;
1016 goto out;
1017 }
1018 if (isdigit(input_buf[0])) {
1019 int new_level = ((int) input_buf[0] - (int) '0');
1020 debug_set_level(id, new_level);
1021 } else if(input_buf[0] == '-') {
1022 debug_set_level(id, DEBUG_OFF_LEVEL);
1023 } else {
1024 printk(KERN_INFO "debug: level `%c` is not valid\n",
1025 input_buf[0]);
1026 }
1027 out:
1028 *offset += in_buf_size;
1029 return rc; /* number of input characters */
1030 }
1031
1032 /*
1033 * prints debug header in raw format
1034 */
1035
1036 int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1037 int area, debug_entry_t * entry, char *out_buf)
1038 {
1039 int rc;
1040
1041 rc = sizeof(debug_entry_t);
1042 memcpy(out_buf,entry,sizeof(debug_entry_t));
1043 return rc;
1044 }
1045
1046 /*
1047 * prints debug data in raw format
1048 */
1049
1050 static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1051 char *out_buf, const char *in_buf)
1052 {
1053 int rc;
1054
1055 rc = id->buf_size;
1056 memcpy(out_buf, in_buf, id->buf_size);
1057 return rc;
1058 }
1059
1060 /*
1061 * prints debug data in hex/ascii format
1062 */
1063
1064 static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1065 char *out_buf, const char *in_buf)
1066 {
1067 int i, rc = 0;
1068
1069 for (i = 0; i < id->buf_size; i++) {
1070 rc += sprintf(out_buf + rc, "%02x ",
1071 ((unsigned char *) in_buf)[i]);
1072 }
1073 rc += sprintf(out_buf + rc, "| ");
1074 for (i = 0; i < id->buf_size; i++) {
1075 unsigned char c = in_buf[i];
1076 if (!isprint(c))
1077 rc += sprintf(out_buf + rc, ".");
1078 else
1079 rc += sprintf(out_buf + rc, "%c", c);
1080 }
1081 rc += sprintf(out_buf + rc, "\n");
1082 return rc;
1083 }
1084
1085 /*
1086 * prints header for debug entry
1087 */
1088
1089 int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1090 int area, debug_entry_t * entry, char *out_buf)
1091 {
1092 struct timeval time_val;
1093 unsigned long long time;
1094 char *except_str;
1095 unsigned long caller;
1096 int rc = 0;
1097 unsigned int level;
1098
1099 level = entry->id.fields.level;
1100 time = entry->id.stck;
1101 /* adjust todclock to 1970 */
1102 time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
1103 tod_to_timeval(time, &time_val);
1104
1105 if (entry->id.fields.exception)
1106 except_str = "*";
1107 else
1108 except_str = "-";
1109 caller = (unsigned long) entry->caller;
1110 #if defined(CONFIG_ARCH_S390X)
1111 rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %016lx ",
1112 area, time_val.tv_sec, time_val.tv_usec, level,
1113 except_str, entry->id.fields.cpuid, caller);
1114 #else
1115 caller &= 0x7fffffff;
1116 rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %08lx ",
1117 area, time_val.tv_sec, time_val.tv_usec, level,
1118 except_str, entry->id.fields.cpuid, caller);
1119 #endif
1120 return rc;
1121 }
1122
1123 /*
1124 * prints debug data sprintf-formated:
1125 * debug_sprinf_event/exception calls must be used together with this view
1126 */
1127
1128 #define DEBUG_SPRINTF_MAX_ARGS 10
1129
1130 int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
1131 char *out_buf, debug_sprintf_entry *curr_event)
1132 {
1133 int num_longs, num_used_args = 0,i, rc = 0;
1134 int index[DEBUG_SPRINTF_MAX_ARGS];
1135
1136 /* count of longs fit into one entry */
1137 num_longs = id->buf_size / sizeof(long);
1138
1139 if(num_longs < 1)
1140 goto out; /* bufsize of entry too small */
1141 if(num_longs == 1) {
1142 /* no args, we use only the string */
1143 strcpy(out_buf, curr_event->string);
1144 rc = strlen(curr_event->string);
1145 goto out;
1146 }
1147
1148 /* number of arguments used for sprintf (without the format string) */
1149 num_used_args = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
1150
1151 memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
1152
1153 for(i = 0; i < num_used_args; i++)
1154 index[i] = i;
1155
1156 rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
1157 curr_event->args[index[1]], curr_event->args[index[2]],
1158 curr_event->args[index[3]], curr_event->args[index[4]],
1159 curr_event->args[index[5]], curr_event->args[index[6]],
1160 curr_event->args[index[7]], curr_event->args[index[8]],
1161 curr_event->args[index[9]]);
1162
1163 out:
1164
1165 return rc;
1166 }
1167
1168 /*
1169 * init_module:
1170 */
1171
1172 #ifdef MODULE
1173 int init_module(void)
1174 {
1175 int rc = 0;
1176 #ifdef DEBUG
1177 printk("debug_module_init: \n");
1178 #endif
1179 rc = debug_init();
1180 if (rc)
1181 printk(KERN_INFO "debug: an error occurred with debug_init\n");
1182 return rc;
1183 }
1184
1185 /*
1186 * cleanup_module:
1187 */
1188
1189 void cleanup_module(void)
1190 {
1191 #ifdef DEBUG
1192 printk("debug_cleanup_module: \n");
1193 #endif
1194 debug_delete_proc_dir_entry(&proc_root, debug_proc_root_entry);
1195 return;
1196 }
1197
1198 #endif /* MODULE */
1199
1200 EXPORT_SYMBOL(debug_register);
1201 EXPORT_SYMBOL(debug_unregister);
1202 EXPORT_SYMBOL(debug_set_level);
1203 EXPORT_SYMBOL(debug_register_view);
1204 EXPORT_SYMBOL(debug_unregister_view);
1205 EXPORT_SYMBOL(debug_event_common);
1206 EXPORT_SYMBOL(debug_exception_common);
1207 EXPORT_SYMBOL(debug_hex_ascii_view);
1208 EXPORT_SYMBOL(debug_raw_view);
1209 EXPORT_SYMBOL(debug_dflt_header_fn);
1210 EXPORT_SYMBOL(debug_sprintf_view);
1211 EXPORT_SYMBOL(debug_sprintf_exception);
1212 EXPORT_SYMBOL(debug_sprintf_event);
1213