linux/arch/s390/kernel/debug.c
<<
>>
Prefs
   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#define KMSG_COMPONENT "s390dbf"
  14#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  15
  16#include <linux/stddef.h>
  17#include <linux/kernel.h>
  18#include <linux/errno.h>
  19#include <linux/slab.h>
  20#include <linux/ctype.h>
  21#include <linux/sysctl.h>
  22#include <asm/uaccess.h>
  23#include <linux/module.h>
  24#include <linux/init.h>
  25#include <linux/fs.h>
  26#include <linux/debugfs.h>
  27
  28#include <asm/debug.h>
  29
  30#define DEBUG_PROLOG_ENTRY -1
  31
  32#define ALL_AREAS 0 /* copy all debug areas */
  33#define NO_AREAS  1 /* copy no debug areas */
  34
  35/* typedefs */
  36
  37typedef struct file_private_info {
  38        loff_t offset;                  /* offset of last read in file */
  39        int    act_area;                /* number of last formated area */
  40        int    act_page;                /* act page in given area */
  41        int    act_entry;               /* last formated entry (offset */
  42                                        /* relative to beginning of last */
  43                                        /* formated page) */
  44        size_t act_entry_offset;        /* up to this offset we copied */
  45                                        /* in last read the last formated */
  46                                        /* entry to userland */
  47        char   temp_buf[2048];          /* buffer for output */
  48        debug_info_t *debug_info_org;   /* original debug information */
  49        debug_info_t *debug_info_snap;  /* snapshot of debug information */
  50        struct debug_view *view;        /* used view of debug info */
  51} file_private_info_t;
  52
  53typedef struct
  54{
  55        char *string;
  56        /* 
  57         * This assumes that all args are converted into longs 
  58         * on L/390 this is the case for all types of parameter 
  59         * except of floats, and long long (32 bit) 
  60         *
  61         */
  62        long args[0];
  63} debug_sprintf_entry_t;
  64
  65
  66/* internal function prototyes */
  67
  68static int debug_init(void);
  69static ssize_t debug_output(struct file *file, char __user *user_buf,
  70                        size_t user_len, loff_t * offset);
  71static ssize_t debug_input(struct file *file, const char __user *user_buf,
  72                        size_t user_len, loff_t * offset);
  73static int debug_open(struct inode *inode, struct file *file);
  74static int debug_close(struct inode *inode, struct file *file);
  75static debug_info_t *debug_info_create(const char *name, int pages_per_area,
  76                        int nr_areas, int buf_size, mode_t mode);
  77static void debug_info_get(debug_info_t *);
  78static void debug_info_put(debug_info_t *);
  79static int debug_prolog_level_fn(debug_info_t * id,
  80                        struct debug_view *view, char *out_buf);
  81static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
  82                        struct file *file, const char __user *user_buf,
  83                        size_t user_buf_size, loff_t * offset);
  84static int debug_prolog_pages_fn(debug_info_t * id,
  85                        struct debug_view *view, char *out_buf);
  86static int debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
  87                        struct file *file, const char __user *user_buf,
  88                        size_t user_buf_size, loff_t * offset);
  89static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
  90                        struct file *file, const char __user *user_buf,
  91                        size_t user_buf_size, loff_t * offset);
  92static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
  93                        char *out_buf, const char *in_buf);
  94static int debug_raw_format_fn(debug_info_t * id,
  95                        struct debug_view *view, char *out_buf,
  96                        const char *in_buf);
  97static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
  98                        int area, debug_entry_t * entry, char *out_buf);
  99
 100static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
 101                        char *out_buf, debug_sprintf_entry_t *curr_event);
 102
 103/* globals */
 104
 105struct debug_view debug_raw_view = {
 106        "raw",
 107        NULL,
 108        &debug_raw_header_fn,
 109        &debug_raw_format_fn,
 110        NULL,
 111        NULL
 112};
 113
 114struct debug_view debug_hex_ascii_view = {
 115        "hex_ascii",
 116        NULL,
 117        &debug_dflt_header_fn,
 118        &debug_hex_ascii_format_fn,
 119        NULL,
 120        NULL
 121};
 122
 123static struct debug_view debug_level_view = {
 124        "level",
 125        &debug_prolog_level_fn,
 126        NULL,
 127        NULL,
 128        &debug_input_level_fn,
 129        NULL
 130};
 131
 132static struct debug_view debug_pages_view = {
 133        "pages",
 134        &debug_prolog_pages_fn,
 135        NULL,
 136        NULL,
 137        &debug_input_pages_fn,
 138        NULL
 139};
 140
 141static struct debug_view debug_flush_view = {
 142        "flush",
 143        NULL,
 144        NULL,
 145        NULL,
 146        &debug_input_flush_fn,
 147        NULL
 148};
 149
 150struct debug_view debug_sprintf_view = {
 151        "sprintf",
 152        NULL,
 153        &debug_dflt_header_fn,
 154        (debug_format_proc_t*)&debug_sprintf_format_fn,
 155        NULL,
 156        NULL
 157};
 158
 159/* used by dump analysis tools to determine version of debug feature */
 160static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
 161
 162/* static globals */
 163
 164static debug_info_t *debug_area_first = NULL;
 165static debug_info_t *debug_area_last = NULL;
 166static DEFINE_MUTEX(debug_mutex);
 167
 168static int initialized;
 169
 170static const struct file_operations debug_file_ops = {
 171        .owner   = THIS_MODULE,
 172        .read    = debug_output,
 173        .write   = debug_input,
 174        .open    = debug_open,
 175        .release = debug_close,
 176};
 177
 178static struct dentry *debug_debugfs_root_entry;
 179
 180/* functions */
 181
 182/*
 183 * debug_areas_alloc
 184 * - Debug areas are implemented as a threedimensonal array:
 185 *   areas[areanumber][pagenumber][pageoffset]
 186 */
 187
 188static debug_entry_t***
 189debug_areas_alloc(int pages_per_area, int nr_areas)
 190{
 191        debug_entry_t*** areas;
 192        int i,j;
 193
 194        areas = kmalloc(nr_areas *
 195                                        sizeof(debug_entry_t**),
 196                                        GFP_KERNEL);
 197        if (!areas)
 198                goto fail_malloc_areas;
 199        for (i = 0; i < nr_areas; i++) {
 200                areas[i] = kmalloc(pages_per_area *
 201                                sizeof(debug_entry_t*),GFP_KERNEL);
 202                if (!areas[i]) {
 203                        goto fail_malloc_areas2;
 204                }
 205                for(j = 0; j < pages_per_area; j++) {
 206                        areas[i][j] = kzalloc(PAGE_SIZE, GFP_KERNEL);
 207                        if(!areas[i][j]) {
 208                                for(j--; j >=0 ; j--) {
 209                                        kfree(areas[i][j]);
 210                                }
 211                                kfree(areas[i]);
 212                                goto fail_malloc_areas2;
 213                        }
 214                }
 215        }
 216        return areas;
 217
 218fail_malloc_areas2:
 219        for(i--; i >= 0; i--){
 220                for(j=0; j < pages_per_area;j++){
 221                        kfree(areas[i][j]);
 222                }
 223                kfree(areas[i]);
 224        }
 225        kfree(areas);
 226fail_malloc_areas:
 227        return NULL;
 228
 229}
 230
 231
 232/*
 233 * debug_info_alloc
 234 * - alloc new debug-info
 235 */
 236
 237static debug_info_t*
 238debug_info_alloc(const char *name, int pages_per_area, int nr_areas,
 239                 int buf_size, int level, int mode)
 240{
 241        debug_info_t* rc;
 242
 243        /* alloc everything */
 244
 245        rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
 246        if(!rc)
 247                goto fail_malloc_rc;
 248        rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
 249        if(!rc->active_entries)
 250                goto fail_malloc_active_entries;
 251        rc->active_pages = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
 252        if(!rc->active_pages)
 253                goto fail_malloc_active_pages;
 254        if((mode == ALL_AREAS) && (pages_per_area != 0)){
 255                rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
 256                if(!rc->areas)
 257                        goto fail_malloc_areas;
 258        } else {
 259                rc->areas = NULL;
 260        }
 261
 262        /* initialize members */
 263
 264        spin_lock_init(&rc->lock);
 265        rc->pages_per_area = pages_per_area;
 266        rc->nr_areas       = nr_areas;
 267        rc->active_area    = 0;
 268        rc->level          = level;
 269        rc->buf_size       = buf_size;
 270        rc->entry_size     = sizeof(debug_entry_t) + buf_size;
 271        strlcpy(rc->name, name, sizeof(rc->name));
 272        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
 273        memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
 274                sizeof(struct dentry*));
 275        atomic_set(&(rc->ref_count), 0);
 276
 277        return rc;
 278
 279fail_malloc_areas:
 280        kfree(rc->active_pages);
 281fail_malloc_active_pages:
 282        kfree(rc->active_entries);
 283fail_malloc_active_entries:
 284        kfree(rc);
 285fail_malloc_rc:
 286        return NULL;
 287}
 288
 289/*
 290 * debug_areas_free
 291 * - free all debug areas
 292 */
 293
 294static void
 295debug_areas_free(debug_info_t* db_info)
 296{
 297        int i,j;
 298
 299        if(!db_info->areas)
 300                return;
 301        for (i = 0; i < db_info->nr_areas; i++) {
 302                for(j = 0; j < db_info->pages_per_area; j++) {
 303                        kfree(db_info->areas[i][j]);
 304                }
 305                kfree(db_info->areas[i]);
 306        }
 307        kfree(db_info->areas);
 308        db_info->areas = NULL;
 309}
 310
 311/*
 312 * debug_info_free
 313 * - free memory debug-info
 314 */
 315
 316static void
 317debug_info_free(debug_info_t* db_info){
 318        debug_areas_free(db_info);
 319        kfree(db_info->active_entries);
 320        kfree(db_info->active_pages);
 321        kfree(db_info);
 322}
 323
 324/*
 325 * debug_info_create
 326 * - create new debug-info
 327 */
 328
 329static debug_info_t*
 330debug_info_create(const char *name, int pages_per_area, int nr_areas,
 331                  int buf_size, mode_t mode)
 332{
 333        debug_info_t* rc;
 334
 335        rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
 336                                DEBUG_DEFAULT_LEVEL, ALL_AREAS);
 337        if(!rc) 
 338                goto out;
 339
 340        rc->mode = mode & ~S_IFMT;
 341
 342        /* create root directory */
 343        rc->debugfs_root_entry = debugfs_create_dir(rc->name,
 344                                        debug_debugfs_root_entry);
 345
 346        /* append new element to linked list */
 347        if (!debug_area_first) {
 348                /* first element in list */
 349                debug_area_first = rc;
 350                rc->prev = NULL;
 351        } else {
 352                /* append element to end of list */
 353                debug_area_last->next = rc;
 354                rc->prev = debug_area_last;
 355        }
 356        debug_area_last = rc;
 357        rc->next = NULL;
 358
 359        debug_info_get(rc);
 360out:
 361        return rc;
 362}
 363
 364/*
 365 * debug_info_copy
 366 * - copy debug-info
 367 */
 368
 369static debug_info_t*
 370debug_info_copy(debug_info_t* in, int mode)
 371{
 372        int i,j;
 373        debug_info_t* rc;
 374        unsigned long flags;
 375
 376        /* get a consistent copy of the debug areas */
 377        do {
 378                rc = debug_info_alloc(in->name, in->pages_per_area,
 379                        in->nr_areas, in->buf_size, in->level, mode);
 380                spin_lock_irqsave(&in->lock, flags);
 381                if(!rc)
 382                        goto out;
 383                /* has something changed in the meantime ? */
 384                if((rc->pages_per_area == in->pages_per_area) &&
 385                   (rc->nr_areas == in->nr_areas)) {
 386                        break;
 387                }
 388                spin_unlock_irqrestore(&in->lock, flags);
 389                debug_info_free(rc);
 390        } while (1);
 391
 392        if (mode == NO_AREAS)
 393                goto out;
 394
 395        for(i = 0; i < in->nr_areas; i++){
 396                for(j = 0; j < in->pages_per_area; j++) {
 397                        memcpy(rc->areas[i][j], in->areas[i][j],PAGE_SIZE);
 398                }
 399        }
 400out:
 401        spin_unlock_irqrestore(&in->lock, flags);
 402        return rc;
 403}
 404
 405/*
 406 * debug_info_get
 407 * - increments reference count for debug-info
 408 */
 409
 410static void
 411debug_info_get(debug_info_t * db_info)
 412{
 413        if (db_info)
 414                atomic_inc(&db_info->ref_count);
 415}
 416
 417/*
 418 * debug_info_put:
 419 * - decreases reference count for debug-info and frees it if necessary
 420 */
 421
 422static void
 423debug_info_put(debug_info_t *db_info)
 424{
 425        int i;
 426
 427        if (!db_info)
 428                return;
 429        if (atomic_dec_and_test(&db_info->ref_count)) {
 430                for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
 431                        if (!db_info->views[i])
 432                                continue;
 433                        debugfs_remove(db_info->debugfs_entries[i]);
 434                }
 435                debugfs_remove(db_info->debugfs_root_entry);
 436                if(db_info == debug_area_first)
 437                        debug_area_first = db_info->next;
 438                if(db_info == debug_area_last)
 439                        debug_area_last = db_info->prev;
 440                if(db_info->prev) db_info->prev->next = db_info->next;
 441                if(db_info->next) db_info->next->prev = db_info->prev;
 442                debug_info_free(db_info);
 443        }
 444}
 445
 446/*
 447 * debug_format_entry:
 448 * - format one debug entry and return size of formated data
 449 */
 450
 451static int
 452debug_format_entry(file_private_info_t *p_info)
 453{
 454        debug_info_t *id_snap   = p_info->debug_info_snap;
 455        struct debug_view *view = p_info->view;
 456        debug_entry_t *act_entry;
 457        size_t len = 0;
 458        if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
 459                /* print prolog */
 460                if (view->prolog_proc)
 461                        len += view->prolog_proc(id_snap,view,p_info->temp_buf);
 462                goto out;
 463        }
 464        if (!id_snap->areas) /* this is true, if we have a prolog only view */
 465                goto out;    /* or if 'pages_per_area' is 0 */
 466        act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area]
 467                                [p_info->act_page] + p_info->act_entry);
 468                        
 469        if (act_entry->id.stck == 0LL)
 470                        goto out;  /* empty entry */
 471        if (view->header_proc)
 472                len += view->header_proc(id_snap, view, p_info->act_area,
 473                                        act_entry, p_info->temp_buf + len);
 474        if (view->format_proc)
 475                len += view->format_proc(id_snap, view, p_info->temp_buf + len,
 476                                                DEBUG_DATA(act_entry));
 477out:
 478        return len;
 479}
 480
 481/*
 482 * debug_next_entry:
 483 * - goto next entry in p_info
 484 */
 485
 486static inline int
 487debug_next_entry(file_private_info_t *p_info)
 488{
 489        debug_info_t *id;
 490
 491        id = p_info->debug_info_snap;
 492        if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
 493                p_info->act_entry = 0;
 494                p_info->act_page  = 0;
 495                goto out;
 496        }
 497        if(!id->areas)
 498                return 1;
 499        p_info->act_entry += id->entry_size;
 500        /* switch to next page, if we reached the end of the page  */
 501        if (p_info->act_entry > (PAGE_SIZE - id->entry_size)){
 502                /* next page */
 503                p_info->act_entry = 0;
 504                p_info->act_page += 1;
 505                if((p_info->act_page % id->pages_per_area) == 0) {
 506                        /* next area */
 507                        p_info->act_area++;
 508                        p_info->act_page=0;
 509                }
 510                if(p_info->act_area >= id->nr_areas)
 511                        return 1;
 512        }
 513out:
 514        return 0;       
 515}
 516
 517/*
 518 * debug_output:
 519 * - called for user read()
 520 * - copies formated debug entries to the user buffer
 521 */
 522
 523static ssize_t
 524debug_output(struct file *file,         /* file descriptor */
 525            char __user *user_buf,      /* user buffer */
 526            size_t  len,                /* length of buffer */
 527            loff_t *offset)             /* offset in the file */
 528{
 529        size_t count = 0;
 530        size_t entry_offset;
 531        file_private_info_t *p_info;
 532
 533        p_info = ((file_private_info_t *) file->private_data);
 534        if (*offset != p_info->offset) 
 535                return -EPIPE;
 536        if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
 537                return 0;
 538        entry_offset = p_info->act_entry_offset;
 539        while(count < len){
 540                int formatted_line_size;
 541                int formatted_line_residue;
 542                int user_buf_residue;
 543                size_t copy_size;
 544
 545                formatted_line_size = debug_format_entry(p_info);
 546                formatted_line_residue = formatted_line_size - entry_offset;
 547                user_buf_residue = len-count;
 548                copy_size = min(user_buf_residue, formatted_line_residue);
 549                if(copy_size){
 550                        if (copy_to_user(user_buf + count, p_info->temp_buf
 551                                        + entry_offset, copy_size))
 552                                return -EFAULT;
 553                        count += copy_size;
 554                        entry_offset += copy_size;
 555                }
 556                if(copy_size == formatted_line_residue){
 557                        entry_offset = 0;
 558                        if(debug_next_entry(p_info))
 559                                goto out;
 560                }
 561        }
 562out:
 563        p_info->offset           = *offset + count;
 564        p_info->act_entry_offset = entry_offset;
 565        *offset = p_info->offset;
 566        return count;
 567}
 568
 569/*
 570 * debug_input:
 571 * - called for user write()
 572 * - calls input function of view
 573 */
 574
 575static ssize_t
 576debug_input(struct file *file, const char __user *user_buf, size_t length,
 577                loff_t *offset)
 578{
 579        int rc = 0;
 580        file_private_info_t *p_info;
 581
 582        mutex_lock(&debug_mutex);
 583        p_info = ((file_private_info_t *) file->private_data);
 584        if (p_info->view->input_proc)
 585                rc = p_info->view->input_proc(p_info->debug_info_org,
 586                                              p_info->view, file, user_buf,
 587                                              length, offset);
 588        else
 589                rc = -EPERM;
 590        mutex_unlock(&debug_mutex);
 591        return rc;              /* number of input characters */
 592}
 593
 594/*
 595 * debug_open:
 596 * - called for user open()
 597 * - copies formated output to private_data area of the file
 598 *   handle
 599 */
 600
 601static int
 602debug_open(struct inode *inode, struct file *file)
 603{
 604        int i, rc = 0;
 605        file_private_info_t *p_info;
 606        debug_info_t *debug_info, *debug_info_snapshot;
 607
 608        mutex_lock(&debug_mutex);
 609        debug_info = file->f_path.dentry->d_inode->i_private;
 610        /* find debug view */
 611        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
 612                if (!debug_info->views[i])
 613                        continue;
 614                else if (debug_info->debugfs_entries[i] ==
 615                         file->f_path.dentry) {
 616                        goto found;     /* found view ! */
 617                }
 618        }
 619        /* no entry found */
 620        rc = -EINVAL;
 621        goto out;
 622
 623found:
 624
 625        /* Make snapshot of current debug areas to get it consistent.     */
 626        /* To copy all the areas is only needed, if we have a view which  */
 627        /* formats the debug areas. */
 628
 629        if(!debug_info->views[i]->format_proc &&
 630                !debug_info->views[i]->header_proc){
 631                debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
 632        } else {
 633                debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
 634        }
 635
 636        if(!debug_info_snapshot){
 637                rc = -ENOMEM;
 638                goto out;
 639        }
 640        p_info = kmalloc(sizeof(file_private_info_t),
 641                                                GFP_KERNEL);
 642        if(!p_info){
 643                debug_info_free(debug_info_snapshot);
 644                rc = -ENOMEM;
 645                goto out;
 646        }
 647        p_info->offset = 0;
 648        p_info->debug_info_snap = debug_info_snapshot;
 649        p_info->debug_info_org  = debug_info;
 650        p_info->view = debug_info->views[i];
 651        p_info->act_area = 0;
 652        p_info->act_page = 0;
 653        p_info->act_entry = DEBUG_PROLOG_ENTRY;
 654        p_info->act_entry_offset = 0;
 655        file->private_data = p_info;
 656        debug_info_get(debug_info);
 657out:
 658        mutex_unlock(&debug_mutex);
 659        return rc;
 660}
 661
 662/*
 663 * debug_close:
 664 * - called for user close()
 665 * - deletes  private_data area of the file handle
 666 */
 667
 668static int
 669debug_close(struct inode *inode, struct file *file)
 670{
 671        file_private_info_t *p_info;
 672        p_info = (file_private_info_t *) file->private_data;
 673        if(p_info->debug_info_snap)
 674                debug_info_free(p_info->debug_info_snap);
 675        debug_info_put(p_info->debug_info_org);
 676        kfree(file->private_data);
 677        return 0;               /* success */
 678}
 679
 680/*
 681 * debug_register_mode:
 682 * - Creates and initializes debug area for the caller
 683 *   The mode parameter allows to specify access rights for the s390dbf files
 684 * - Returns handle for debug area
 685 */
 686
 687debug_info_t *debug_register_mode(const char *name, int pages_per_area,
 688                                  int nr_areas, int buf_size, mode_t mode,
 689                                  uid_t uid, gid_t gid)
 690{
 691        debug_info_t *rc = NULL;
 692
 693        /* Since debugfs currently does not support uid/gid other than root, */
 694        /* we do not allow gid/uid != 0 until we get support for that. */
 695        if ((uid != 0) || (gid != 0))
 696                pr_warning("Root becomes the owner of all s390dbf files "
 697                           "in sysfs\n");
 698        BUG_ON(!initialized);
 699        mutex_lock(&debug_mutex);
 700
 701        /* create new debug_info */
 702
 703        rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
 704        if(!rc) 
 705                goto out;
 706        debug_register_view(rc, &debug_level_view);
 707        debug_register_view(rc, &debug_flush_view);
 708        debug_register_view(rc, &debug_pages_view);
 709out:
 710        if (!rc){
 711                pr_err("Registering debug feature %s failed\n", name);
 712        }
 713        mutex_unlock(&debug_mutex);
 714        return rc;
 715}
 716EXPORT_SYMBOL(debug_register_mode);
 717
 718/*
 719 * debug_register:
 720 * - creates and initializes debug area for the caller
 721 * - returns handle for debug area
 722 */
 723
 724debug_info_t *debug_register(const char *name, int pages_per_area,
 725                             int nr_areas, int buf_size)
 726{
 727        return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
 728                                   S_IRUSR | S_IWUSR, 0, 0);
 729}
 730
 731/*
 732 * debug_unregister:
 733 * - give back debug area
 734 */
 735
 736void
 737debug_unregister(debug_info_t * id)
 738{
 739        if (!id)
 740                goto out;
 741        mutex_lock(&debug_mutex);
 742        debug_info_put(id);
 743        mutex_unlock(&debug_mutex);
 744
 745out:
 746        return;
 747}
 748
 749/*
 750 * debug_set_size:
 751 * - set area size (number of pages) and number of areas
 752 */
 753static int
 754debug_set_size(debug_info_t* id, int nr_areas, int pages_per_area)
 755{
 756        unsigned long flags;
 757        debug_entry_t *** new_areas;
 758        int rc=0;
 759
 760        if(!id || (nr_areas <= 0) || (pages_per_area < 0))
 761                return -EINVAL;
 762        if(pages_per_area > 0){
 763                new_areas = debug_areas_alloc(pages_per_area, nr_areas);
 764                if(!new_areas) {
 765                        pr_info("Allocating memory for %i pages failed\n",
 766                                pages_per_area);
 767                        rc = -ENOMEM;
 768                        goto out;
 769                }
 770        } else {
 771                new_areas = NULL;
 772        }
 773        spin_lock_irqsave(&id->lock,flags);
 774        debug_areas_free(id);
 775        id->areas = new_areas;
 776        id->nr_areas = nr_areas;
 777        id->pages_per_area = pages_per_area;
 778        id->active_area = 0;
 779        memset(id->active_entries,0,sizeof(int)*id->nr_areas);
 780        memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
 781        spin_unlock_irqrestore(&id->lock,flags);
 782        pr_info("%s: set new size (%i pages)\n" ,id->name, pages_per_area);
 783out:
 784        return rc;
 785}
 786
 787/*
 788 * debug_set_level:
 789 * - set actual debug level
 790 */
 791
 792void
 793debug_set_level(debug_info_t* id, int new_level)
 794{
 795        unsigned long flags;
 796        if(!id)
 797                return; 
 798        spin_lock_irqsave(&id->lock,flags);
 799        if(new_level == DEBUG_OFF_LEVEL){
 800                id->level = DEBUG_OFF_LEVEL;
 801                pr_info("%s: switched off\n",id->name);
 802        } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
 803                pr_info("%s: level %i is out of range (%i - %i)\n",
 804                        id->name, new_level, 0, DEBUG_MAX_LEVEL);
 805        } else {
 806                id->level = new_level;
 807        }
 808        spin_unlock_irqrestore(&id->lock,flags);
 809}
 810
 811
 812/*
 813 * proceed_active_entry:
 814 * - set active entry to next in the ring buffer
 815 */
 816
 817static inline void
 818proceed_active_entry(debug_info_t * id)
 819{
 820        if ((id->active_entries[id->active_area] += id->entry_size)
 821            > (PAGE_SIZE - id->entry_size)){
 822                id->active_entries[id->active_area] = 0;
 823                id->active_pages[id->active_area] =
 824                        (id->active_pages[id->active_area] + 1) %
 825                        id->pages_per_area;
 826        }
 827}
 828
 829/*
 830 * proceed_active_area:
 831 * - set active area to next in the ring buffer
 832 */
 833
 834static inline void
 835proceed_active_area(debug_info_t * id)
 836{
 837        id->active_area++;
 838        id->active_area = id->active_area % id->nr_areas;
 839}
 840
 841/*
 842 * get_active_entry:
 843 */
 844
 845static inline debug_entry_t*
 846get_active_entry(debug_info_t * id)
 847{
 848        return (debug_entry_t *) (((char *) id->areas[id->active_area]
 849                                        [id->active_pages[id->active_area]]) +
 850                                        id->active_entries[id->active_area]);
 851}
 852
 853/*
 854 * debug_finish_entry:
 855 * - set timestamp, caller address, cpu number etc.
 856 */
 857
 858static inline void
 859debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
 860                        int exception)
 861{
 862        active->id.stck = get_clock();
 863        active->id.fields.cpuid = smp_processor_id();
 864        active->caller = __builtin_return_address(0);
 865        active->id.fields.exception = exception;
 866        active->id.fields.level     = level;
 867        proceed_active_entry(id);
 868        if(exception)
 869                proceed_active_area(id);
 870}
 871
 872static int debug_stoppable=1;
 873static int debug_active=1;
 874
 875#define CTL_S390DBF_STOPPABLE 5678
 876#define CTL_S390DBF_ACTIVE 5679
 877
 878/*
 879 * proc handler for the running debug_active sysctl
 880 * always allow read, allow write only if debug_stoppable is set or
 881 * if debug_active is already off
 882 */
 883static int
 884s390dbf_procactive(ctl_table *table, int write,
 885                     void __user *buffer, size_t *lenp, loff_t *ppos)
 886{
 887        if (!write || debug_stoppable || !debug_active)
 888                return proc_dointvec(table, write, buffer, lenp, ppos);
 889        else
 890                return 0;
 891}
 892
 893
 894static struct ctl_table s390dbf_table[] = {
 895        {
 896                .ctl_name       = CTL_S390DBF_STOPPABLE,
 897                .procname       = "debug_stoppable",
 898                .data           = &debug_stoppable,
 899                .maxlen         = sizeof(int),
 900                .mode           = S_IRUGO | S_IWUSR,
 901                .proc_handler   = &proc_dointvec,
 902                .strategy       = &sysctl_intvec,
 903        },
 904         {
 905                .ctl_name       = CTL_S390DBF_ACTIVE,
 906                .procname       = "debug_active",
 907                .data           = &debug_active,
 908                .maxlen         = sizeof(int),
 909                .mode           = S_IRUGO | S_IWUSR,
 910                .proc_handler   = &s390dbf_procactive,
 911                .strategy       = &sysctl_intvec,
 912        },
 913        { .ctl_name = 0 }
 914};
 915
 916static struct ctl_table s390dbf_dir_table[] = {
 917        {
 918                .ctl_name       = CTL_S390DBF,
 919                .procname       = "s390dbf",
 920                .maxlen         = 0,
 921                .mode           = S_IRUGO | S_IXUGO,
 922                .child          = s390dbf_table,
 923        },
 924        { .ctl_name = 0 }
 925};
 926
 927static struct ctl_table_header *s390dbf_sysctl_header;
 928
 929void
 930debug_stop_all(void)
 931{
 932        if (debug_stoppable)
 933                debug_active = 0;
 934}
 935
 936
 937/*
 938 * debug_event_common:
 939 * - write debug entry with given size
 940 */
 941
 942debug_entry_t*
 943debug_event_common(debug_info_t * id, int level, const void *buf, int len)
 944{
 945        unsigned long flags;
 946        debug_entry_t *active;
 947
 948        if (!debug_active || !id->areas)
 949                return NULL;
 950        spin_lock_irqsave(&id->lock, flags);
 951        active = get_active_entry(id);
 952        memset(DEBUG_DATA(active), 0, id->buf_size);
 953        memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 954        debug_finish_entry(id, active, level, 0);
 955        spin_unlock_irqrestore(&id->lock, flags);
 956
 957        return active;
 958}
 959
 960/*
 961 * debug_exception_common:
 962 * - write debug entry with given size and switch to next debug area
 963 */
 964
 965debug_entry_t
 966*debug_exception_common(debug_info_t * id, int level, const void *buf, int len)
 967{
 968        unsigned long flags;
 969        debug_entry_t *active;
 970
 971        if (!debug_active || !id->areas)
 972                return NULL;
 973        spin_lock_irqsave(&id->lock, flags);
 974        active = get_active_entry(id);
 975        memset(DEBUG_DATA(active), 0, id->buf_size);
 976        memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
 977        debug_finish_entry(id, active, level, 1);
 978        spin_unlock_irqrestore(&id->lock, flags);
 979
 980        return active;
 981}
 982
 983/*
 984 * counts arguments in format string for sprintf view
 985 */
 986
 987static inline int
 988debug_count_numargs(char *string)
 989{
 990        int numargs=0;
 991
 992        while(*string) {
 993                if(*string++=='%')
 994                        numargs++;
 995        }
 996        return(numargs);
 997}
 998
 999/*
1000 * debug_sprintf_event:
1001 */
1002
1003debug_entry_t*
1004debug_sprintf_event(debug_info_t* id, int level,char *string,...)
1005{
1006        va_list   ap;
1007        int numargs,idx;
1008        unsigned long flags;
1009        debug_sprintf_entry_t *curr_event;
1010        debug_entry_t *active;
1011
1012        if((!id) || (level > id->level))
1013                return NULL;
1014        if (!debug_active || !id->areas)
1015                return NULL;
1016        numargs=debug_count_numargs(string);
1017
1018        spin_lock_irqsave(&id->lock, flags);
1019        active = get_active_entry(id);
1020        curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
1021        va_start(ap,string);
1022        curr_event->string=string;
1023        for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
1024                curr_event->args[idx]=va_arg(ap,long);
1025        va_end(ap);
1026        debug_finish_entry(id, active, level, 0);
1027        spin_unlock_irqrestore(&id->lock, flags);
1028
1029        return active;
1030}
1031
1032/*
1033 * debug_sprintf_exception:
1034 */
1035
1036debug_entry_t*
1037debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
1038{
1039        va_list   ap;
1040        int numargs,idx;
1041        unsigned long flags;
1042        debug_sprintf_entry_t *curr_event;
1043        debug_entry_t *active;
1044
1045        if((!id) || (level > id->level))
1046                return NULL;
1047        if (!debug_active || !id->areas)
1048                return NULL;
1049
1050        numargs=debug_count_numargs(string);
1051
1052        spin_lock_irqsave(&id->lock, flags);
1053        active = get_active_entry(id);
1054        curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
1055        va_start(ap,string);
1056        curr_event->string=string;
1057        for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
1058                curr_event->args[idx]=va_arg(ap,long);
1059        va_end(ap);
1060        debug_finish_entry(id, active, level, 1);
1061        spin_unlock_irqrestore(&id->lock, flags);
1062
1063        return active;
1064}
1065
1066/*
1067 * debug_init:
1068 * - is called exactly once to initialize the debug feature
1069 */
1070
1071static int
1072__init debug_init(void)
1073{
1074        int rc = 0;
1075
1076        s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
1077        mutex_lock(&debug_mutex);
1078        debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
1079        initialized = 1;
1080        mutex_unlock(&debug_mutex);
1081
1082        return rc;
1083}
1084
1085/*
1086 * debug_register_view:
1087 */
1088
1089int
1090debug_register_view(debug_info_t * id, struct debug_view *view)
1091{
1092        int rc = 0;
1093        int i;
1094        unsigned long flags;
1095        mode_t mode;
1096        struct dentry *pde;
1097
1098        if (!id)
1099                goto out;
1100        mode = (id->mode | S_IFREG) & ~S_IXUGO;
1101        if (!(view->prolog_proc || view->format_proc || view->header_proc))
1102                mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
1103        if (!view->input_proc)
1104                mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
1105        pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
1106                                id , &debug_file_ops);
1107        if (!pde){
1108                pr_err("Registering view %s/%s failed due to out of "
1109                       "memory\n", id->name,view->name);
1110                rc = -1;
1111                goto out;
1112        }
1113        spin_lock_irqsave(&id->lock, flags);
1114        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
1115                if (!id->views[i])
1116                        break;
1117        }
1118        if (i == DEBUG_MAX_VIEWS) {
1119                pr_err("Registering view %s/%s would exceed the maximum "
1120                       "number of views %i\n", id->name, view->name, i);
1121                debugfs_remove(pde);
1122                rc = -1;
1123        } else {
1124                id->views[i] = view;
1125                id->debugfs_entries[i] = pde;
1126        }
1127        spin_unlock_irqrestore(&id->lock, flags);
1128out:
1129        return rc;
1130}
1131
1132/*
1133 * debug_unregister_view:
1134 */
1135
1136int
1137debug_unregister_view(debug_info_t * id, struct debug_view *view)
1138{
1139        int rc = 0;
1140        int i;
1141        unsigned long flags;
1142
1143        if (!id)
1144                goto out;
1145        spin_lock_irqsave(&id->lock, flags);
1146        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
1147                if (id->views[i] == view)
1148                        break;
1149        }
1150        if (i == DEBUG_MAX_VIEWS)
1151                rc = -1;
1152        else {
1153                debugfs_remove(id->debugfs_entries[i]);
1154                id->views[i] = NULL;
1155        }
1156        spin_unlock_irqrestore(&id->lock, flags);
1157out:
1158        return rc;
1159}
1160
1161static inline char *
1162debug_get_user_string(const char __user *user_buf, size_t user_len)
1163{
1164        char* buffer;
1165
1166        buffer = kmalloc(user_len + 1, GFP_KERNEL);
1167        if (!buffer)
1168                return ERR_PTR(-ENOMEM);
1169        if (copy_from_user(buffer, user_buf, user_len) != 0) {
1170                kfree(buffer);
1171                return ERR_PTR(-EFAULT);
1172        }
1173        /* got the string, now strip linefeed. */
1174        if (buffer[user_len - 1] == '\n')
1175                buffer[user_len - 1] = 0;
1176        else
1177                buffer[user_len] = 0;
1178        return buffer;
1179}
1180
1181static inline int
1182debug_get_uint(char *buf)
1183{
1184        int rc;
1185
1186        for(; isspace(*buf); buf++);
1187        rc = simple_strtoul(buf, &buf, 10);
1188        if(*buf){
1189                rc = -EINVAL;
1190        }
1191        return rc;
1192}
1193
1194/*
1195 * functions for debug-views
1196 ***********************************
1197*/
1198
1199/*
1200 * prints out actual debug level
1201 */
1202
1203static int
1204debug_prolog_pages_fn(debug_info_t * id,
1205                                 struct debug_view *view, char *out_buf)
1206{
1207        return sprintf(out_buf, "%i\n", id->pages_per_area);
1208}
1209
1210/*
1211 * reads new size (number of pages per debug area)
1212 */
1213
1214static int
1215debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
1216                        struct file *file, const char __user *user_buf,
1217                        size_t user_len, loff_t * offset)
1218{
1219        char *str;
1220        int rc,new_pages;
1221
1222        if (user_len > 0x10000)
1223                user_len = 0x10000;
1224        if (*offset != 0){
1225                rc = -EPIPE;
1226                goto out;
1227        }
1228        str = debug_get_user_string(user_buf,user_len);
1229        if(IS_ERR(str)){
1230                rc = PTR_ERR(str);
1231                goto out;
1232        }
1233        new_pages = debug_get_uint(str);
1234        if(new_pages < 0){
1235                rc = -EINVAL;
1236                goto free_str;
1237        }
1238        rc = debug_set_size(id,id->nr_areas, new_pages);
1239        if(rc != 0){
1240                rc = -EINVAL;
1241                goto free_str;
1242        }
1243        rc = user_len;
1244free_str:
1245        kfree(str);
1246out:
1247        *offset += user_len;
1248        return rc;              /* number of input characters */
1249}
1250
1251/*
1252 * prints out actual debug level
1253 */
1254
1255static int
1256debug_prolog_level_fn(debug_info_t * id, struct debug_view *view, char *out_buf)
1257{
1258        int rc = 0;
1259
1260        if(id->level == DEBUG_OFF_LEVEL) {
1261                rc = sprintf(out_buf,"-\n");
1262        }
1263        else {
1264                rc = sprintf(out_buf, "%i\n", id->level);
1265        }
1266        return rc;
1267}
1268
1269/*
1270 * reads new debug level
1271 */
1272
1273static int
1274debug_input_level_fn(debug_info_t * id, struct debug_view *view,
1275                        struct file *file, const char __user *user_buf,
1276                        size_t user_len, loff_t * offset)
1277{
1278        char *str;
1279        int rc,new_level;
1280
1281        if (user_len > 0x10000)
1282                user_len = 0x10000;
1283        if (*offset != 0){
1284                rc = -EPIPE;
1285                goto out;
1286        }
1287        str = debug_get_user_string(user_buf,user_len);
1288        if(IS_ERR(str)){
1289                rc = PTR_ERR(str);
1290                goto out;
1291        }
1292        if(str[0] == '-'){
1293                debug_set_level(id, DEBUG_OFF_LEVEL);
1294                rc = user_len;
1295                goto free_str;
1296        } else {
1297                new_level = debug_get_uint(str);
1298        }
1299        if(new_level < 0) {
1300                pr_warning("%s is not a valid level for a debug "
1301                           "feature\n", str);
1302                rc = -EINVAL;
1303        } else {
1304                debug_set_level(id, new_level);
1305                rc = user_len;
1306        }
1307free_str:
1308        kfree(str);
1309out:
1310        *offset += user_len;
1311        return rc;              /* number of input characters */
1312}
1313
1314
1315/*
1316 * flushes debug areas
1317 */
1318 
1319static void debug_flush(debug_info_t* id, int area)
1320{
1321        unsigned long flags;
1322        int i,j;
1323
1324        if(!id || !id->areas)
1325                return;
1326        spin_lock_irqsave(&id->lock,flags);
1327        if(area == DEBUG_FLUSH_ALL){
1328                id->active_area = 0;
1329                memset(id->active_entries, 0, id->nr_areas * sizeof(int));
1330                for (i = 0; i < id->nr_areas; i++) {
1331                        id->active_pages[i] = 0;
1332                        for(j = 0; j < id->pages_per_area; j++) {
1333                                memset(id->areas[i][j], 0, PAGE_SIZE);
1334                        }
1335                }
1336        } else if(area >= 0 && area < id->nr_areas) {
1337                id->active_entries[area] = 0;
1338                id->active_pages[area] = 0;
1339                for(i = 0; i < id->pages_per_area; i++) {
1340                        memset(id->areas[area][i],0,PAGE_SIZE);
1341                }
1342        }
1343        spin_unlock_irqrestore(&id->lock,flags);
1344}
1345
1346/*
1347 * view function: flushes debug areas 
1348 */
1349
1350static int
1351debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
1352                        struct file *file, const char __user *user_buf,
1353                        size_t user_len, loff_t * offset)
1354{
1355        char input_buf[1];
1356        int rc = user_len;
1357
1358        if (user_len > 0x10000)
1359                user_len = 0x10000;
1360        if (*offset != 0){
1361                rc = -EPIPE;
1362                goto out;
1363        }
1364        if (copy_from_user(input_buf, user_buf, 1)){
1365                rc = -EFAULT;
1366                goto out;
1367        }
1368        if(input_buf[0] == '-') { 
1369                debug_flush(id, DEBUG_FLUSH_ALL);
1370                goto out;
1371        }
1372        if (isdigit(input_buf[0])) {
1373                int area = ((int) input_buf[0] - (int) '0');
1374                debug_flush(id, area);
1375                goto out;
1376        }
1377
1378        pr_info("Flushing debug data failed because %c is not a valid "
1379                 "area\n", input_buf[0]);
1380
1381out:
1382        *offset += user_len;
1383        return rc;              /* number of input characters */
1384}
1385
1386/*
1387 * prints debug header in raw format
1388 */
1389
1390static int
1391debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
1392                        int area, debug_entry_t * entry, char *out_buf)
1393{
1394        int rc;
1395
1396        rc = sizeof(debug_entry_t);
1397        memcpy(out_buf,entry,sizeof(debug_entry_t));
1398        return rc;
1399}
1400
1401/*
1402 * prints debug data in raw format
1403 */
1404
1405static int
1406debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
1407                               char *out_buf, const char *in_buf)
1408{
1409        int rc;
1410
1411        rc = id->buf_size;
1412        memcpy(out_buf, in_buf, id->buf_size);
1413        return rc;
1414}
1415
1416/*
1417 * prints debug data in hex/ascii format
1418 */
1419
1420static int
1421debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
1422                          char *out_buf, const char *in_buf)
1423{
1424        int i, rc = 0;
1425
1426        for (i = 0; i < id->buf_size; i++) {
1427                rc += sprintf(out_buf + rc, "%02x ",
1428                              ((unsigned char *) in_buf)[i]);
1429        }
1430        rc += sprintf(out_buf + rc, "| ");
1431        for (i = 0; i < id->buf_size; i++) {
1432                unsigned char c = in_buf[i];
1433                if (!isprint(c))
1434                        rc += sprintf(out_buf + rc, ".");
1435                else
1436                        rc += sprintf(out_buf + rc, "%c", c);
1437        }
1438        rc += sprintf(out_buf + rc, "\n");
1439        return rc;
1440}
1441
1442/*
1443 * prints header for debug entry
1444 */
1445
1446int
1447debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
1448                         int area, debug_entry_t * entry, char *out_buf)
1449{
1450        struct timespec time_spec;
1451        char *except_str;
1452        unsigned long caller;
1453        int rc = 0;
1454        unsigned int level;
1455
1456        level = entry->id.fields.level;
1457        stck_to_timespec(entry->id.stck, &time_spec);
1458
1459        if (entry->id.fields.exception)
1460                except_str = "*";
1461        else
1462                except_str = "-";
1463        caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN;
1464        rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p  ",
1465                      area, time_spec.tv_sec, time_spec.tv_nsec / 1000, level,
1466                      except_str, entry->id.fields.cpuid, (void *) caller);
1467        return rc;
1468}
1469
1470/*
1471 * prints debug data sprintf-formated:
1472 * debug_sprinf_event/exception calls must be used together with this view
1473 */
1474
1475#define DEBUG_SPRINTF_MAX_ARGS 10
1476
1477static int
1478debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
1479                        char *out_buf, debug_sprintf_entry_t *curr_event)
1480{
1481        int num_longs, num_used_args = 0,i, rc = 0;
1482        int index[DEBUG_SPRINTF_MAX_ARGS];
1483
1484        /* count of longs fit into one entry */
1485        num_longs = id->buf_size /  sizeof(long); 
1486
1487        if(num_longs < 1)
1488                goto out; /* bufsize of entry too small */
1489        if(num_longs == 1) {
1490                /* no args, we use only the string */
1491                strcpy(out_buf, curr_event->string);
1492                rc = strlen(curr_event->string);
1493                goto out;
1494        }
1495
1496        /* number of arguments used for sprintf (without the format string) */
1497        num_used_args   = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
1498
1499        memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
1500
1501        for(i = 0; i < num_used_args; i++)
1502                index[i] = i;
1503
1504        rc =  sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
1505                curr_event->args[index[1]], curr_event->args[index[2]],
1506                curr_event->args[index[3]], curr_event->args[index[4]],
1507                curr_event->args[index[5]], curr_event->args[index[6]],
1508                curr_event->args[index[7]], curr_event->args[index[8]],
1509                curr_event->args[index[9]]);
1510
1511out:
1512
1513        return rc;
1514}
1515
1516/*
1517 * clean up module
1518 */
1519static void __exit debug_exit(void)
1520{
1521        debugfs_remove(debug_debugfs_root_entry);
1522        unregister_sysctl_table(s390dbf_sysctl_header);
1523        return;
1524}
1525
1526/*
1527 * module definitions
1528 */
1529postcore_initcall(debug_init);
1530module_exit(debug_exit);
1531MODULE_LICENSE("GPL");
1532
1533EXPORT_SYMBOL(debug_register);
1534EXPORT_SYMBOL(debug_unregister); 
1535EXPORT_SYMBOL(debug_set_level);
1536EXPORT_SYMBOL(debug_stop_all);
1537EXPORT_SYMBOL(debug_register_view);
1538EXPORT_SYMBOL(debug_unregister_view);
1539EXPORT_SYMBOL(debug_event_common);
1540EXPORT_SYMBOL(debug_exception_common);
1541EXPORT_SYMBOL(debug_hex_ascii_view);
1542EXPORT_SYMBOL(debug_raw_view);
1543EXPORT_SYMBOL(debug_dflt_header_fn);
1544EXPORT_SYMBOL(debug_sprintf_view);
1545EXPORT_SYMBOL(debug_sprintf_exception);
1546EXPORT_SYMBOL(debug_sprintf_event);
1547