• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  *   S/390 debug facility
4  *
5  *    Copyright IBM Corp. 1999, 2000
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 <uapi/asm/debug.h>
16 
17 #define DEBUG_MAX_LEVEL		   6  /* debug levels range from 0 to 6 */
18 #define DEBUG_OFF_LEVEL		   -1 /* level where debug is switched off */
19 #define DEBUG_FLUSH_ALL		   -1 /* parameter to flush all areas */
20 #define DEBUG_MAX_VIEWS		   10 /* max number of views in proc fs */
21 #define DEBUG_MAX_NAME_LEN	   64 /* max length for a debugfs file name */
22 #define DEBUG_DEFAULT_LEVEL	   3  /* initial debug level */
23 
24 #define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
25 
26 #define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */
27 					      /* the entry information */
28 
29 typedef struct __debug_entry debug_entry_t;
30 
31 struct debug_view;
32 
33 typedef struct debug_info {
34 	struct debug_info *next;
35 	struct debug_info *prev;
36 	refcount_t ref_count;
37 	spinlock_t lock;
38 	int level;
39 	int nr_areas;
40 	int pages_per_area;
41 	int buf_size;
42 	int entry_size;
43 	debug_entry_t ***areas;
44 	int active_area;
45 	int *active_pages;
46 	int *active_entries;
47 	struct dentry *debugfs_root_entry;
48 	struct dentry *debugfs_entries[DEBUG_MAX_VIEWS];
49 	struct debug_view *views[DEBUG_MAX_VIEWS];
50 	char name[DEBUG_MAX_NAME_LEN];
51 	umode_t mode;
52 } debug_info_t;
53 
54 typedef int (debug_header_proc_t) (debug_info_t *id,
55 				   struct debug_view *view,
56 				   int area,
57 				   debug_entry_t *entry,
58 				   char *out_buf);
59 
60 typedef int (debug_format_proc_t) (debug_info_t *id,
61 				   struct debug_view *view, char *out_buf,
62 				   const char *in_buf);
63 typedef int (debug_prolog_proc_t) (debug_info_t *id,
64 				   struct debug_view *view,
65 				   char *out_buf);
66 typedef int (debug_input_proc_t) (debug_info_t *id,
67 				  struct debug_view *view,
68 				  struct file *file,
69 				  const char __user *user_buf,
70 				  size_t in_buf_size, loff_t *offset);
71 
72 int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
73 			 int area, debug_entry_t *entry, char *out_buf);
74 
75 struct debug_view {
76 	char name[DEBUG_MAX_NAME_LEN];
77 	debug_prolog_proc_t *prolog_proc;
78 	debug_header_proc_t *header_proc;
79 	debug_format_proc_t *format_proc;
80 	debug_input_proc_t  *input_proc;
81 	void		    *private_data;
82 };
83 
84 extern struct debug_view debug_hex_ascii_view;
85 extern struct debug_view debug_raw_view;
86 extern struct debug_view debug_sprintf_view;
87 
88 /* do NOT use the _common functions */
89 
90 debug_entry_t *debug_event_common(debug_info_t *id, int level,
91 				  const void *data, int length);
92 
93 debug_entry_t *debug_exception_common(debug_info_t *id, int level,
94 				      const void *data, int length);
95 
96 /* Debug Feature API: */
97 
98 debug_info_t *debug_register(const char *name, int pages, int nr_areas,
99 			     int buf_size);
100 
101 debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas,
102 				  int buf_size, umode_t mode, uid_t uid,
103 				  gid_t gid);
104 
105 void debug_unregister(debug_info_t *id);
106 
107 void debug_set_level(debug_info_t *id, int new_level);
108 
109 void debug_set_critical(void);
110 
111 void debug_stop_all(void);
112 
113 /**
114  * debug_level_enabled() - Returns true if debug events for the specified
115  *			   level would be logged. Otherwise returns false.
116  *
117  * @id:		handle for debug log
118  * @level:	debug level
119  *
120  * Return:
121  * - %true if level is less or equal to the current debug level.
122  */
debug_level_enabled(debug_info_t * id,int level)123 static inline bool debug_level_enabled(debug_info_t *id, int level)
124 {
125 	return level <= id->level;
126 }
127 
128 /**
129  * debug_event() - writes binary debug entry to active debug area
130  *		   (if level <= actual debug level)
131  *
132  * @id:		handle for debug log
133  * @level:	debug level
134  * @data:	pointer to data for debug entry
135  * @length:	length of data in bytes
136  *
137  * Return:
138  * - Address of written debug entry
139  * - %NULL if error
140  */
debug_event(debug_info_t * id,int level,void * data,int length)141 static inline debug_entry_t *debug_event(debug_info_t *id, int level,
142 					 void *data, int length)
143 {
144 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
145 		return NULL;
146 	return debug_event_common(id, level, data, length);
147 }
148 
149 /**
150  * debug_int_event() - writes unsigned integer debug entry to active debug area
151  *		       (if level <= actual debug level)
152  *
153  * @id:		handle for debug log
154  * @level:	debug level
155  * @tag:	integer value for debug entry
156  *
157  * Return:
158  * - Address of written debug entry
159  * - %NULL if error
160  */
debug_int_event(debug_info_t * id,int level,unsigned int tag)161 static inline debug_entry_t *debug_int_event(debug_info_t *id, int level,
162 					     unsigned int tag)
163 {
164 	unsigned int t = tag;
165 
166 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
167 		return NULL;
168 	return debug_event_common(id, level, &t, sizeof(unsigned int));
169 }
170 
171 /**
172  * debug_long_event() - writes unsigned long debug entry to active debug area
173  *		       (if level <= actual debug level)
174  *
175  * @id:		handle for debug log
176  * @level:	debug level
177  * @tag:	long integer value for debug entry
178  *
179  * Return:
180  * - Address of written debug entry
181  * - %NULL if error
182  */
debug_long_event(debug_info_t * id,int level,unsigned long tag)183 static inline debug_entry_t *debug_long_event(debug_info_t *id, int level,
184 					      unsigned long tag)
185 {
186 	unsigned long t = tag;
187 
188 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
189 		return NULL;
190 	return debug_event_common(id, level, &t, sizeof(unsigned long));
191 }
192 
193 /**
194  * debug_text_event() - writes string debug entry in ascii format to active
195  *			debug area (if level <= actual debug level)
196  *
197  * @id:		handle for debug log
198  * @level:	debug level
199  * @txt:	string for debug entry
200  *
201  * Return:
202  * - Address of written debug entry
203  * - %NULL if error
204  */
debug_text_event(debug_info_t * id,int level,const char * txt)205 static inline debug_entry_t *debug_text_event(debug_info_t *id, int level,
206 					      const char *txt)
207 {
208 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
209 		return NULL;
210 	return debug_event_common(id, level, txt, strlen(txt));
211 }
212 
213 /*
214  * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
215  * stored in the s390dbf. See Documentation/s390/s390dbf.rst for more details!
216  */
217 extern debug_entry_t *
218 __debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
219 	__attribute__ ((format(printf, 3, 4)));
220 
221 /**
222  * debug_sprintf_event() - writes debug entry with format string
223  *			   and varargs (longs) to active debug area
224  *			   (if level $<=$ actual debug level).
225  *
226  * @_id:	handle for debug log
227  * @_level:	debug level
228  * @_fmt:	format string for debug entry
229  * @...:	varargs used as in sprintf()
230  *
231  * Return:
232  * - Address of written debug entry
233  * - %NULL if error
234  *
235  * floats and long long datatypes cannot be used as varargs.
236  */
237 #define debug_sprintf_event(_id, _level, _fmt, ...)			\
238 ({									\
239 	debug_entry_t *__ret;						\
240 	debug_info_t *__id = _id;					\
241 	int __level = _level;						\
242 									\
243 	if ((!__id) || (__level > __id->level))				\
244 		__ret = NULL;						\
245 	else								\
246 		__ret = __debug_sprintf_event(__id, __level,		\
247 					      _fmt, ## __VA_ARGS__);	\
248 	__ret;								\
249 })
250 
251 /**
252  * debug_exception() - writes binary debug entry to active debug area
253  *		       (if level <= actual debug level)
254  *		       and switches to next debug area
255  *
256  * @id:		handle for debug log
257  * @level:	debug level
258  * @data:	pointer to data for debug entry
259  * @length:	length of data in bytes
260  *
261  * Return:
262  * - Address of written debug entry
263  * - %NULL if error
264  */
debug_exception(debug_info_t * id,int level,void * data,int length)265 static inline debug_entry_t *debug_exception(debug_info_t *id, int level,
266 					     void *data, int length)
267 {
268 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
269 		return NULL;
270 	return debug_exception_common(id, level, data, length);
271 }
272 
273 /**
274  * debug_int_exception() - writes unsigned int debug entry to active debug area
275  *			   (if level <= actual debug level)
276  *			   and switches to next debug area
277  *
278  * @id:		handle for debug log
279  * @level:	debug level
280  * @tag:	integer value for debug entry
281  *
282  * Return:
283  * - Address of written debug entry
284  * - %NULL if error
285  */
debug_int_exception(debug_info_t * id,int level,unsigned int tag)286 static inline debug_entry_t *debug_int_exception(debug_info_t *id, int level,
287 						 unsigned int tag)
288 {
289 	unsigned int t = tag;
290 
291 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
292 		return NULL;
293 	return debug_exception_common(id, level, &t, sizeof(unsigned int));
294 }
295 
296 /**
297  * debug_long_exception() - writes long debug entry to active debug area
298  *			   (if level <= actual debug level)
299  *			   and switches to next debug area
300  *
301  * @id:		handle for debug log
302  * @level:	debug level
303  * @tag:	long integer value for debug entry
304  *
305  * Return:
306  * - Address of written debug entry
307  * - %NULL if error
308  */
debug_long_exception(debug_info_t * id,int level,unsigned long tag)309 static inline debug_entry_t *debug_long_exception (debug_info_t *id, int level,
310 						   unsigned long tag)
311 {
312 	unsigned long t = tag;
313 
314 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
315 		return NULL;
316 	return debug_exception_common(id, level, &t, sizeof(unsigned long));
317 }
318 
319 /**
320  * debug_text_exception() - writes string debug entry in ascii format to active
321  *			    debug area (if level <= actual debug level)
322  *			    and switches to next debug area
323  * area
324  *
325  * @id:	handle for debug log
326  * @level:	debug level
327  * @txt:	string for debug entry
328  *
329  * Return:
330  * - Address of written debug entry
331  * - %NULL if error
332  */
debug_text_exception(debug_info_t * id,int level,const char * txt)333 static inline debug_entry_t *debug_text_exception(debug_info_t *id, int level,
334 						  const char *txt)
335 {
336 	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
337 		return NULL;
338 	return debug_exception_common(id, level, txt, strlen(txt));
339 }
340 
341 /*
342  * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
343  * stored in the s390dbf. See Documentation/s390/s390dbf.rst for more details!
344  */
345 extern debug_entry_t *
346 __debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
347 	__attribute__ ((format(printf, 3, 4)));
348 
349 
350 /**
351  * debug_sprintf_exception() - writes debug entry with format string and
352  *			       varargs (longs) to active debug area
353  *			       (if level <= actual debug level)
354  *			       and switches to next debug area.
355  *
356  * @_id:	handle for debug log
357  * @_level:	debug level
358  * @_fmt:	format string for debug entry
359  * @...:	varargs used as in sprintf()
360  *
361  * Return:
362  * - Address of written debug entry
363  * - %NULL if error
364  *
365  * floats and long long datatypes cannot be used as varargs.
366  */
367 #define debug_sprintf_exception(_id, _level, _fmt, ...)			\
368 ({									\
369 	debug_entry_t *__ret;						\
370 	debug_info_t *__id = _id;					\
371 	int __level = _level;						\
372 									\
373 	if ((!__id) || (__level > __id->level))				\
374 		__ret = NULL;						\
375 	else								\
376 		__ret = __debug_sprintf_exception(__id, __level,	\
377 						  _fmt, ## __VA_ARGS__);\
378 	__ret;								\
379 })
380 
381 int debug_register_view(debug_info_t *id, struct debug_view *view);
382 
383 int debug_unregister_view(debug_info_t *id, struct debug_view *view);
384 
385 /*
386    define the debug levels:
387    - 0 No debugging output to console or syslog
388    - 1 Log internal errors to syslog, ignore check conditions
389    - 2 Log internal errors and check conditions to syslog
390    - 3 Log internal errors to console, log check conditions to syslog
391    - 4 Log internal errors and check conditions to console
392    - 5 panic on internal errors, log check conditions to console
393    - 6 panic on both, internal errors and check conditions
394  */
395 
396 #ifndef DEBUG_LEVEL
397 #define DEBUG_LEVEL 4
398 #endif
399 
400 #define INTERNAL_ERRMSG(x,y...) "E" __FILE__ "%d: " x, __LINE__, y
401 #define INTERNAL_WRNMSG(x,y...) "W" __FILE__ "%d: " x, __LINE__, y
402 #define INTERNAL_INFMSG(x,y...) "I" __FILE__ "%d: " x, __LINE__, y
403 #define INTERNAL_DEBMSG(x,y...) "D" __FILE__ "%d: " x, __LINE__, y
404 
405 #if DEBUG_LEVEL > 0
406 #define PRINT_DEBUG(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
407 #define PRINT_INFO(x...)	printk(KERN_INFO PRINTK_HEADER x)
408 #define PRINT_WARN(x...)	printk(KERN_WARNING PRINTK_HEADER x)
409 #define PRINT_ERR(x...)		printk(KERN_ERR PRINTK_HEADER x)
410 #define PRINT_FATAL(x...)	panic(PRINTK_HEADER x)
411 #else
412 #define PRINT_DEBUG(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
413 #define PRINT_INFO(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
414 #define PRINT_WARN(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
415 #define PRINT_ERR(x...)		printk(KERN_DEBUG PRINTK_HEADER x)
416 #define PRINT_FATAL(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
417 #endif /* DASD_DEBUG */
418 
419 #endif /* DEBUG_H */
420