debug.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:31k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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