1
2
3
4
5
6
7#ifndef DEBUG_H
8#define DEBUG_H
9
10#include <linux/string.h>
11#include <linux/spinlock.h>
12#include <linux/kernel.h>
13#include <linux/time.h>
14#include <linux/refcount.h>
15#include <linux/fs.h>
16#include <linux/init.h>
17
18#define DEBUG_MAX_LEVEL 6
19#define DEBUG_OFF_LEVEL -1
20#define DEBUG_FLUSH_ALL -1
21#define DEBUG_MAX_VIEWS 10
22#define DEBUG_MAX_NAME_LEN 64
23#define DEBUG_DEFAULT_LEVEL 3
24
25#define DEBUG_DIR_ROOT "s390dbf"
26
27#define DEBUG_DATA(entry) (char *)(entry + 1)
28
29
30#define __DEBUG_FEATURE_VERSION 3
31
32struct __debug_entry {
33 unsigned long clock : 60;
34 unsigned long exception : 1;
35 unsigned long level : 3;
36 void *caller;
37 unsigned short cpu;
38} __packed;
39
40typedef struct __debug_entry debug_entry_t;
41
42struct debug_view;
43
44typedef struct debug_info {
45 struct debug_info *next;
46 struct debug_info *prev;
47 refcount_t ref_count;
48 spinlock_t lock;
49 int level;
50 int nr_areas;
51 int pages_per_area;
52 int buf_size;
53 int entry_size;
54 debug_entry_t ***areas;
55 int active_area;
56 int *active_pages;
57 int *active_entries;
58 struct dentry *debugfs_root_entry;
59 struct dentry *debugfs_entries[DEBUG_MAX_VIEWS];
60 struct debug_view *views[DEBUG_MAX_VIEWS];
61 char name[DEBUG_MAX_NAME_LEN];
62 umode_t mode;
63} debug_info_t;
64
65typedef int (debug_header_proc_t) (debug_info_t *id,
66 struct debug_view *view,
67 int area,
68 debug_entry_t *entry,
69 char *out_buf);
70
71typedef int (debug_format_proc_t) (debug_info_t *id,
72 struct debug_view *view, char *out_buf,
73 const char *in_buf);
74typedef int (debug_prolog_proc_t) (debug_info_t *id,
75 struct debug_view *view,
76 char *out_buf);
77typedef int (debug_input_proc_t) (debug_info_t *id,
78 struct debug_view *view,
79 struct file *file,
80 const char __user *user_buf,
81 size_t in_buf_size, loff_t *offset);
82
83int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
84 int area, debug_entry_t *entry, char *out_buf);
85
86struct debug_view {
87 char name[DEBUG_MAX_NAME_LEN];
88 debug_prolog_proc_t *prolog_proc;
89 debug_header_proc_t *header_proc;
90 debug_format_proc_t *format_proc;
91 debug_input_proc_t *input_proc;
92 void *private_data;
93};
94
95extern struct debug_view debug_hex_ascii_view;
96extern struct debug_view debug_sprintf_view;
97
98
99
100debug_entry_t *debug_event_common(debug_info_t *id, int level,
101 const void *data, int length);
102
103debug_entry_t *debug_exception_common(debug_info_t *id, int level,
104 const void *data, int length);
105
106
107
108debug_info_t *debug_register(const char *name, int pages, int nr_areas,
109 int buf_size);
110
111debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas,
112 int buf_size, umode_t mode, uid_t uid,
113 gid_t gid);
114
115void debug_unregister(debug_info_t *id);
116
117void debug_set_level(debug_info_t *id, int new_level);
118
119void debug_set_critical(void);
120
121void debug_stop_all(void);
122
123
124
125
126
127
128
129
130
131
132
133static inline bool debug_level_enabled(debug_info_t *id, int level)
134{
135 return level <= id->level;
136}
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151static inline debug_entry_t *debug_event(debug_info_t *id, int level,
152 void *data, int length)
153{
154 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
155 return NULL;
156 return debug_event_common(id, level, data, length);
157}
158
159
160
161
162
163
164
165
166
167
168
169
170
171static inline debug_entry_t *debug_int_event(debug_info_t *id, int level,
172 unsigned int tag)
173{
174 unsigned int t = tag;
175
176 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
177 return NULL;
178 return debug_event_common(id, level, &t, sizeof(unsigned int));
179}
180
181
182
183
184
185
186
187
188
189
190
191
192
193static inline debug_entry_t *debug_long_event(debug_info_t *id, int level,
194 unsigned long tag)
195{
196 unsigned long t = tag;
197
198 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
199 return NULL;
200 return debug_event_common(id, level, &t, sizeof(unsigned long));
201}
202
203
204
205
206
207
208
209
210
211
212
213
214
215static inline debug_entry_t *debug_text_event(debug_info_t *id, int level,
216 const char *txt)
217{
218 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
219 return NULL;
220 return debug_event_common(id, level, txt, strlen(txt));
221}
222
223
224
225
226
227extern debug_entry_t *
228__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
229 __attribute__ ((format(printf, 3, 4)));
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247#define debug_sprintf_event(_id, _level, _fmt, ...) \
248({ \
249 debug_entry_t *__ret; \
250 debug_info_t *__id = _id; \
251 int __level = _level; \
252 \
253 if ((!__id) || (__level > __id->level)) \
254 __ret = NULL; \
255 else \
256 __ret = __debug_sprintf_event(__id, __level, \
257 _fmt, ## __VA_ARGS__); \
258 __ret; \
259})
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275static inline debug_entry_t *debug_exception(debug_info_t *id, int level,
276 void *data, int length)
277{
278 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
279 return NULL;
280 return debug_exception_common(id, level, data, length);
281}
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296static inline debug_entry_t *debug_int_exception(debug_info_t *id, int level,
297 unsigned int tag)
298{
299 unsigned int t = tag;
300
301 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
302 return NULL;
303 return debug_exception_common(id, level, &t, sizeof(unsigned int));
304}
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319static inline debug_entry_t *debug_long_exception (debug_info_t *id, int level,
320 unsigned long tag)
321{
322 unsigned long t = tag;
323
324 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
325 return NULL;
326 return debug_exception_common(id, level, &t, sizeof(unsigned long));
327}
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343static inline debug_entry_t *debug_text_exception(debug_info_t *id, int level,
344 const char *txt)
345{
346 if ((!id) || (level > id->level) || (id->pages_per_area == 0))
347 return NULL;
348 return debug_exception_common(id, level, txt, strlen(txt));
349}
350
351
352
353
354
355extern debug_entry_t *
356__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
357 __attribute__ ((format(printf, 3, 4)));
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377#define debug_sprintf_exception(_id, _level, _fmt, ...) \
378({ \
379 debug_entry_t *__ret; \
380 debug_info_t *__id = _id; \
381 int __level = _level; \
382 \
383 if ((!__id) || (__level > __id->level)) \
384 __ret = NULL; \
385 else \
386 __ret = __debug_sprintf_exception(__id, __level, \
387 _fmt, ## __VA_ARGS__);\
388 __ret; \
389})
390
391int debug_register_view(debug_info_t *id, struct debug_view *view);
392
393int debug_unregister_view(debug_info_t *id, struct debug_view *view);
394
395#ifndef MODULE
396
397
398
399
400
401
402#define EARLY_PAGES 8
403#define EARLY_AREAS 1
404
405#define VNAME(var, suffix) __##var##_##suffix
406
407
408
409
410
411
412#define __DEFINE_STATIC_AREA(var) \
413static char VNAME(var, data)[EARLY_PAGES][PAGE_SIZE] __initdata; \
414static debug_entry_t *VNAME(var, pages)[EARLY_PAGES] __initdata = { \
415 (debug_entry_t *)VNAME(var, data)[0], \
416 (debug_entry_t *)VNAME(var, data)[1], \
417 (debug_entry_t *)VNAME(var, data)[2], \
418 (debug_entry_t *)VNAME(var, data)[3], \
419 (debug_entry_t *)VNAME(var, data)[4], \
420 (debug_entry_t *)VNAME(var, data)[5], \
421 (debug_entry_t *)VNAME(var, data)[6], \
422 (debug_entry_t *)VNAME(var, data)[7], \
423}; \
424static debug_entry_t **VNAME(var, areas)[EARLY_AREAS] __initdata = { \
425 (debug_entry_t **)VNAME(var, pages), \
426}; \
427static int VNAME(var, active_pages)[EARLY_AREAS] __initdata; \
428static int VNAME(var, active_entries)[EARLY_AREAS] __initdata
429
430#define __DEBUG_INFO_INIT(var, _name, _buf_size) { \
431 .next = NULL, \
432 .prev = NULL, \
433 .ref_count = REFCOUNT_INIT(1), \
434 .lock = __SPIN_LOCK_UNLOCKED(var.lock), \
435 .level = DEBUG_DEFAULT_LEVEL, \
436 .nr_areas = EARLY_AREAS, \
437 .pages_per_area = EARLY_PAGES, \
438 .buf_size = (_buf_size), \
439 .entry_size = sizeof(debug_entry_t) + (_buf_size), \
440 .areas = VNAME(var, areas), \
441 .active_area = 0, \
442 .active_pages = VNAME(var, active_pages), \
443 .active_entries = VNAME(var, active_entries), \
444 .debugfs_root_entry = NULL, \
445 .debugfs_entries = { NULL }, \
446 .views = { NULL }, \
447 .name = (_name), \
448 .mode = 0600, \
449}
450
451#define __REGISTER_STATIC_DEBUG_INFO(var, name, pages, areas, view) \
452static int __init VNAME(var, reg)(void) \
453{ \
454 debug_register_static(&var, (pages), (areas)); \
455 debug_register_view(&var, (view)); \
456 return 0; \
457} \
458arch_initcall(VNAME(var, reg))
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480#define DEFINE_STATIC_DEBUG_INFO(var, name, pages, nr_areas, buf_size, view) \
481__DEFINE_STATIC_AREA(var); \
482static debug_info_t __refdata var = \
483 __DEBUG_INFO_INIT(var, (name), (buf_size)); \
484__REGISTER_STATIC_DEBUG_INFO(var, name, pages, nr_areas, view)
485
486void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas);
487
488#endif
489
490#endif
491