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