OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [Documentation/] [s390/] [s390dbf.txt] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
S390 Debug Feature
2
==================
3
 
4
files: arch/s390/kernel/debug.c
5
       include/asm-s390/debug.h
6
 
7
Description:
8
------------
9
The goal of this feature is to provide a kernel debug logging API
10
where log records can be stored efficiently in memory, where each component
11
(e.g. device drivers) can have one seperate debug log.
12
One purpose of this is to inspect the debug logs after a production system crash
13
in order to analyze the reason for the crash.
14
If the system still runs but only a subcomponent which uses dbf failes,
15
it is possible to look at the debug logs on a live system via the Linux proc
16
filesystem.
17
The debug feature may also very usefull for kernel and driver development.
18
 
19
Design:
20
-------
21
Kernel components (e.g. device drivers) can register themselves at the debug
22
feature with the function call debug_register(). This function initializes a
23
debug log for the caller. For each debug log exists a number of debug areas
24
where exactly one is active at one time.  Each debug area consists of contiguous
25
pages in memory. In the debug areas there are stored debug entries (log records)
26
which are written by event- and exception-calls.
27
 
28
An event-call writes the specified debug entry to the active debug
29
area and updates the log pointer for the active area. If the end
30
of the active debug area is reached, a wrap around is done (ring buffer)
31
and the next debug entry will be written at the beginning of the active
32
debug area.
33
 
34
An exception-call writes the specified debug entry to the log and
35
switches to the next debug area. This is done in order to be sure
36
that the records which describe the origin of the exception are not
37
overwritten when a wrap around for the current area occurs.
38
 
39
The debug areas itselve are also ordered in form of a ring buffer.
40
When an exception is thrown in the last debug area, the following debug
41
entries are then written again in the very first area.
42
 
43
There are three versions for the event- and exception-calls: One for
44
logging raw data, one for text and one for numbers.
45
 
46
Each debug entry contains the following data:
47
 
48
- Timestamp
49
- Cpu-Number of calling task
50
- Level of debug entry (0...6)
51
- Return Address to caller
52
- Flag, if entry is an exception or not
53
 
54
The debug logs can be inspected in a live system through entries in
55
the proc-filesystem. Under the path /proc/s390dbf there is
56
a directory for each registered component, which is named like the
57
corresponding component.
58
 
59
The content of the directories are files which represent different views
60
to the debug log. Each component can decide which views should be
61
used through registering them with the function debug_register_view().
62
Predefined views for hex/ascii, sprintf and raw binary data are provided.
63
It is also possible to define other views. The content of
64
a view can be inspected simply by reading the corresponding proc file.
65
 
66
All debug logs have an an actual debug level (range from 0 to 6).
67
The default level is 3. Event and Exception functions have a 'level'
68
parameter. Only debug entries with a level that is lower or equal
69
than the actual level are written to the log. This means that high
70
priority log entries should have a low level value whereas low priority
71
entries should have a high one.
72
The actual debug level can be changed with the help of the proc-filesystem
73
through writing a number string "x" to the 'level' proc file which is
74
provided for every debug log. Debugging can be switched off completely
75
by using "-" on the 'level' proc file.
76
 
77
Example:
78
 
79
> echo "-" > /proc/s390dbf/dasd/level
80
 
81
Kernel Interfaces:
82
------------------
83
 
84
----------------------------------------------------------------------------
85
debug_info_t *debug_register(char *name, int pages_index, int nr_areas,
86
                             int buf_size);
87
 
88
Parameter:    name:        Name of debug log (e.g. used for proc entry)
89
              pages_index: 2^pages_index pages will be allocated per area
90
              nr_areas:    number of debug areas
91
              buf_size:    size of data area in each debug entry
92
 
93
Return Value: Handle for generated debug area
94
              NULL if register failed
95
 
96
Description:  Allocates memory for a debug log
97
              Must not be called within an interrupt handler
98
 
99
---------------------------------------------------------------------------
100
void debug_unregister (debug_info_t * id);
101
 
102
Parameter:     id:   handle for debug log
103
 
104
Return Value:  none
105
 
106
Description:   frees memory for a debug log
107
               Must not be called within an interrupt handler
108
 
109
---------------------------------------------------------------------------
110
void debug_set_level (debug_info_t * id, int new_level);
111
 
112
Parameter:     id:        handle for debug log
113
               new_level: new debug level
114
 
115
Return Value:  none
116
 
117
Description:   Sets new actual debug level if new_level is valid.
118
---------------------------------------------------------------------------
119
debug_entry_t* debug_event (debug_info_t* id, int level, void* data,
120
                            int length);
121
 
122
Parameter:     id:     handle for debug log
123
               level:  debug level
124
               data:   pointer to data for debug entry
125
               length: length of data in bytes
126
 
127
Return Value:  Address of written debug entry
128
 
129
Description:   writes debug entry to active debug area (if level <= actual
130
               debug level)
131
 
132
---------------------------------------------------------------------------
133
debug_entry_t* debug_int_event (debug_info_t * id, int level,
134
                                unsigned int data);
135
debug_entry_t* debug_long_event(debug_info_t * id, int level,
136
                                unsigned long data);
137
 
138
Parameter:     id:     handle for debug log
139
               level:  debug level
140
               data:   integer value for debug entry
141
 
142
Return Value:  Address of written debug entry
143
 
144
Description:   writes debug entry to active debug area (if level <= actual
145
               debug level)
146
 
147
---------------------------------------------------------------------------
148
debug_entry_t* debug_text_event (debug_info_t * id, int level,
149
                                 const char* data);
150
 
151
Parameter:     id:     handle for debug log
152
               level:  debug level
153
               data:   string for debug entry
154
 
155
Return Value:  Address of written debug entry
156
 
157
Description:   writes debug entry in ascii format to active debug area
158
               (if level <= actual debug level)
159
 
160
---------------------------------------------------------------------------
161
debug_entry_t* debug_sprintf_event (debug_info_t * id, int level,
162
                                    char* string,...);
163
 
164
Parameter:     id:    handle for debug log
165
               level: debug level
166
               string: format string for debug entry
167
               ...: varargs used as in sprintf()
168
 
169
Return Value:  Address of written debug entry
170
 
171
Description:   writes debug entry with format string and varargs (longs) to
172
               active debug area (if level $<=$ actual debug level).
173
               floats and long long datatypes cannot be used as varargs.
174
 
175
---------------------------------------------------------------------------
176
 
177
debug_entry_t* debug_exception (debug_info_t* id, int level, void* data,
178
                                int length);
179
 
180
Parameter:     id:     handle for debug log
181
               level:  debug level
182
               data:   pointer to data for debug entry
183
               length: length of data in bytes
184
 
185
Return Value:  Address of written debug entry
186
 
187
Description:   writes debug entry to active debug area (if level <= actual
188
               debug level) and switches to next debug area
189
 
190
---------------------------------------------------------------------------
191
debug_entry_t* debug_int_exception (debug_info_t * id, int level,
192
                                    unsigned int data);
193
debug_entry_t* debug_long_exception(debug_info_t * id, int level,
194
                                    unsigned long data);
195
 
196
Parameter:     id:     handle for debug log
197
               level:  debug level
198
               data:   integer value for debug entry
199
 
200
Return Value:  Address of written debug entry
201
 
202
Description:   writes debug entry to active debug area (if level <= actual
203
               debug level) and switches to next debug area
204
 
205
---------------------------------------------------------------------------
206
debug_entry_t* debug_text_exception (debug_info_t * id, int level,
207
                                     const char* data);
208
 
209
Parameter:     id:     handle for debug log
210
               level:  debug level
211
               data:   string for debug entry
212
 
213
Return Value:  Address of written debug entry
214
 
215
Description:   writes debug entry in ascii format to active debug area
216
               (if level <= actual debug level) and switches to next debug
217
               area
218
 
219
---------------------------------------------------------------------------
220
debug_entry_t* debug_sprintf_exception (debug_info_t * id, int level,
221
                                        char* string,...);
222
 
223
Parameter:     id:    handle for debug log
224
               level: debug level
225
               string: format string for debug entry
226
               ...: varargs used as in sprintf()
227
 
228
Return Value:  Address of written debug entry
229
 
230
Description:   writes debug entry with format string and varargs (longs) to
231
               active debug area (if level $<=$ actual debug level) and
232
               switches to next debug area.
233
               floats and long long datatypes cannot be used as varargs.
234
 
235
---------------------------------------------------------------------------
236
 
237
int debug_register_view (debug_info_t * id, struct debug_view *view);
238
 
239
Parameter:     id:    handle for debug log
240
               view:  pointer to debug view struct
241
 
242
Return Value:  0  : ok
243
               < 0: Error
244
 
245
Description:   registers new debug view and creates proc dir entry
246
 
247
---------------------------------------------------------------------------
248
int debug_unregister_view (debug_info_t * id, struct debug_view *view);
249
 
250
Parameter:     id:    handle for debug log
251
               view:  pointer to debug view struct
252
 
253
Return Value:  0  : ok
254
               < 0: Error
255
 
256
Description:   unregisters debug view and removes proc dir entry
257
 
258
 
259
 
260
Predefined views:
261
-----------------
262
 
263
extern struct debug_view debug_hex_ascii_view;
264
extern struct debug_view debug_raw_view;
265
extern struct debug_view debug_sprintf_view;
266
 
267
Examples
268
--------
269
 
270
/*
271
 * hex_ascii- + raw-view Example
272
 */
273
 
274
#include 
275
#include 
276
 
277
static debug_info_t* debug_info;
278
 
279
int init_module(void)
280
{
281
    /* register 4 debug areas with one page each and 4 byte data field */
282
 
283
    debug_info = debug_register ("test", 0, 4, 4 );
284
    debug_register_view(debug_info,&debug_hex_ascii_view);
285
    debug_register_view(debug_info,&debug_raw_view);
286
 
287
    debug_text_event(debug_info, 4 , "one ");
288
    debug_int_exception(debug_info, 4, 4711);
289
    debug_event(debug_info, 3, &debug_info, 4);
290
 
291
    return 0;
292
}
293
 
294
void cleanup_module(void)
295
{
296
    debug_unregister (debug_info);
297
}
298
 
299
---------------------------------------------------------------------------
300
 
301
/*
302
 * sprintf-view Example
303
 */
304
 
305
#include 
306
#include 
307
 
308
static debug_info_t* debug_info;
309
 
310
int init_module(void)
311
{
312
    /* register 4 debug areas with one page each and data field for */
313
    /* format string pointer + 2 varargs (= 3 * sizeof(long))       */
314
 
315
    debug_info = debug_register ("test", 0, 4, sizeof(long) * 3);
316
    debug_register_view(debug_info,&debug_sprintf_view);
317
 
318
    debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__);
319
    debug_sprintf_exception(debug_info, 1, "pointer to debug info: %p\n",&debug_info);
320
 
321
    return 0;
322
}
323
 
324
void cleanup_module(void)
325
{
326
    debug_unregister (debug_info);
327
}
328
 
329
 
330
 
331
ProcFS Interface
332
----------------
333
Views to the debug logs can be investigated through reading the corresponding
334
proc-files:
335
 
336
Example:
337
 
338
> ls /proc/s390dbf/dasd
339
flush  hex_ascii  level      raw
340
> cat /proc/s390dbf/dasd/hex_ascii | sort +1
341
00 00974733272:680099 2 - 02 0006ad7e  07 ea 4a 90 | ....
342
00 00974733272:682210 2 - 02 0006ade6  46 52 45 45 | FREE
343
00 00974733272:682213 2 - 02 0006adf6  07 ea 4a 90 | ....
344
00 00974733272:682281 1 * 02 0006ab08  41 4c 4c 43 | EXCP
345
01 00974733272:682284 2 - 02 0006ab16  45 43 4b 44 | ECKD
346
01 00974733272:682287 2 - 02 0006ab28  00 00 00 04 | ....
347
01 00974733272:682289 2 - 02 0006ab3e  00 00 00 20 | ...
348
01 00974733272:682297 2 - 02 0006ad7e  07 ea 4a 90 | ....
349
01 00974733272:684384 2 - 00 0006ade6  46 52 45 45 | FREE
350
01 00974733272:684388 2 - 00 0006adf6  07 ea 4a 90 | ....
351
 
352
See section about predefined views for explanation of the above output!
353
 
354
Changing the debug level
355
------------------------
356
 
357
Example:
358
 
359
 
360
> cat /proc/s390dbf/dasd/level
361
3
362
> echo "5" > /proc/s390dbf/dasd/level
363
> cat /proc/s390dbf/dasd/level
364
5
365
 
366
Flushing debug areas
367
--------------------
368
Debug areas can be flushed with piping the number of the desired
369
area (0...n) to the proc file "flush". When using "-" all debug areas
370
are flushed.
371
 
372
Examples:
373
 
374
1. Flush debug area 0:
375
> echo "0" > /proc/s390dbf/dasd/flush
376
 
377
2. Flush all debug areas:
378
> echo "-" > /proc/s390dbf/dasd/flush
379
 
380
lcrash Interface
381
----------------
382
It is planned that the dump analysis tool lcrash gets an additional command
383
's390dbf' to display all the debug logs. With this tool it will be possible
384
to investigate the debug logs on a live system and with a memory dump after
385
a system crash.
386
 
387
Investigating raw memory
388
------------------------
389
One last possibility to investigate the debug logs at a live
390
system and after a system crash is to look at the raw memory
391
under VM or at the Service Element.
392
It is possible to find the anker of the debug-logs through
393
the 'debug_area_first' symbol in the System map. Then one has
394
to follow the correct pointers of the data-structures defined
395
in debug.h and find the debug-areas in memory.
396
Normally modules which use the debug feature will also have
397
a global variable with the pointer to the debug-logs. Following
398
this pointer it will also be possible to find the debug logs in
399
memory.
400
 
401
For this method it is recommended to use '16 * x + 4' byte (x = 0..n)
402
for the length of the data field in debug_register() in
403
order to see the debug entries well formatted.
404
 
405
 
406
Predefined Views
407
----------------
408
 
409
There are three predefined views: hex_ascii, raw and sprintf.
410
The hex_ascii view shows the data field in hex and ascii representation
411
(e.g. '45 43 4b 44 | ECKD').
412
The raw view returns a bytestream as the debug areas are stored in memory.
413
 
414
The sprintf view formats the debug entries in the same way as the sprintf
415
function would do. The sprintf event/expection fuctions write to the
416
debug entry a pointer to the format string (size = sizeof(long))
417
and for each vararg a long value. So e.g. for a debug entry with a format
418
string plus two varargs one would need to allocate a (3 * sizeof(long))
419
byte data area in the debug_register() function.
420
 
421
 
422
NOTE: If using the sprintf view do NOT use other event/exception functions
423
than the sprintf-event and -exception functions.
424
 
425
The format of the hex_ascii and sprintf view is as follows:
426
- Number of area
427
- Timestamp (formatted as seconds and microseconds since 00:00:00 Coordinated
428
  Universal Time (UTC), January 1, 1970)
429
- level of debug entry
430
- Exception flag (* = Exception)
431
- Cpu-Number of calling task
432
- Return Address to caller
433
- data field
434
 
435
The format of the raw view is:
436
- Header as described in debug.h
437
- datafield
438
 
439
A typical line of the hex_ascii view will look like the following (first line
440
is only for explanation and will not be displayed when 'cating' the view):
441
 
442
area  time           level exception cpu caller    data (hex + ascii)
443
--------------------------------------------------------------------------
444
00    00964419409:440690 1 -         00  88023fe
445
 
446
 
447
Defining views
448
--------------
449
 
450
Views are specified with the 'debug_view' structure. There are defined
451
callback functions which are used for reading and writing the proc files:
452
 
453
struct debug_view {
454
        char name[DEBUG_MAX_PROCF_LEN];
455
        debug_prolog_proc_t* prolog_proc;
456
        debug_header_proc_t* header_proc;
457
        debug_format_proc_t* format_proc;
458
        debug_input_proc_t*  input_proc;
459
        void*                private_data;
460
};
461
 
462
where
463
 
464
typedef int (debug_header_proc_t) (debug_info_t* id,
465
                                   struct debug_view* view,
466
                                   int area,
467
                                   debug_entry_t* entry,
468
                                   char* out_buf);
469
 
470
typedef int (debug_format_proc_t) (debug_info_t* id,
471
                                   struct debug_view* view, char* out_buf,
472
                                   const char* in_buf);
473
typedef int (debug_prolog_proc_t) (debug_info_t* id,
474
                                   struct debug_view* view,
475
                                   char* out_buf);
476
typedef int (debug_input_proc_t) (debug_info_t* id,
477
                                  struct debug_view* view,
478
                                  struct file* file, const char* user_buf,
479
                                  size_t in_buf_size, loff_t* offset);
480
 
481
 
482
The "private_data" member can be used as pointer to view specific data.
483
It is not used by the debug feature itself.
484
 
485
The output when reading a debug-proc file is structured like this:
486
 
487
"prolog_proc output"
488
 
489
"header_proc output 1"  "format_proc output 1"
490
"header_proc output 2"  "format_proc output 2"
491
"header_proc output 3"  "format_proc output 3"
492
...
493
 
494
When a view is read from the proc fs, the Debug Feature calls the
495
'prolog_proc' once for writing the prolog.
496
Then 'header_proc' and 'format_proc' are called for each
497
existing debug entry.
498
 
499
The input_proc can be used to implement functionality when it is written to
500
the view (e.g. like with 'echo "0" > /proc/s390dbf/dasd/level).
501
 
502
For header_proc there can be used the default function
503
debug_dflt_header_fn() which is defined in in debug.h.
504
and which produces the same header output as the predefined views.
505
E.g:
506
00 00964419409:440761 2 - 00 88023ec
507
 
508
In order to see how to use the callback functions check the implementation
509
of the default views!
510
 
511
Example
512
 
513
#include 
514
 
515
#define UNKNOWNSTR "data: %08x"
516
 
517
const char* messages[] =
518
{"This error...........\n",
519
 "That error...........\n",
520
 "Problem..............\n",
521
 "Something went wrong.\n",
522
 "Everything ok........\n",
523
 NULL
524
};
525
 
526
static int debug_test_format_fn(
527
   debug_info_t * id, struct debug_view *view,
528
   char *out_buf, const char *in_buf
529
)
530
{
531
  int i, rc = 0;
532
 
533
  if(id->buf_size >= 4) {
534
     int msg_nr = *((int*)in_buf);
535
     if(msg_nr < sizeof(messages)/sizeof(char*) - 1)
536
        rc += sprintf(out_buf, "%s", messages[msg_nr]);
537
     else
538
        rc += sprintf(out_buf, UNKNOWNSTR, msg_nr);
539
  }
540
 out:
541
   return rc;
542
}
543
 
544
struct debug_view debug_test_view = {
545
  "myview",                 /* name of view */
546
  NULL,                     /* no prolog */
547
  &debug_dflt_header_fn,    /* default header for each entry */
548
  &debug_test_format_fn,    /* our own format function */
549
  NULL,                     /* no input function */
550
  NULL                      /* no private data */
551
};
552
 
553
=====
554
test:
555
=====
556
debug_info_t *debug_info;
557
...
558
debug_info = debug_register ("test", 0, 4, 4 ));
559
debug_register_view(debug_info, &debug_test_view);
560
for(i = 0; i < 10; i ++) debug_int_event(debug_info, 1, i);
561
 
562
> cat /proc/s390dbf/test/myview
563
00 00964419734:611402 1 - 00 88042ca   This error...........
564
00 00964419734:611405 1 - 00 88042ca   That error...........
565
00 00964419734:611408 1 - 00 88042ca   Problem..............
566
00 00964419734:611411 1 - 00 88042ca   Something went wrong.
567
00 00964419734:611414 1 - 00 88042ca   Everything ok........
568
00 00964419734:611417 1 - 00 88042ca   data: 00000005
569
00 00964419734:611419 1 - 00 88042ca   data: 00000006
570
00 00964419734:611422 1 - 00 88042ca   data: 00000007
571
00 00964419734:611425 1 - 00 88042ca   data: 00000008
572
00 00964419734:611428 1 - 00 88042ca   data: 00000009

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.