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