File Index
Files and directories
Sign in
FILE

debug.h

File preview with syntax highlighting.

linux-6.19.14/arch/s390/include/asm/debug.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 *   S/390 debug facility
  4 *
  5 *    Copyright IBM Corp. 1999, 2020
  6 */
  7#ifndef _ASM_S390_DEBUG_H
  8#define _ASM_S390_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  /* debug levels range from 0 to 6 */
 19#define DEBUG_OFF_LEVEL		   -1 /* level where debug is switched off */
 20#define DEBUG_FLUSH_ALL		   -1 /* parameter to flush all areas */
 21#define DEBUG_MAX_VIEWS		   10 /* max number of views in proc fs */
 22#define DEBUG_MAX_NAME_LEN	   64 /* max length for a debugfs file name */
 23#define DEBUG_DEFAULT_LEVEL	   3  /* initial debug level */
 24
 25#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
 26
 27#define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */
 28					      /* the entry information */
 29
 30#define __DEBUG_FEATURE_VERSION	   3  /* version of debug feature */
 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, size_t out_buf_size);
 70
 71typedef int (debug_format_proc_t) (debug_info_t *id,
 72				   struct debug_view *view, char *out_buf,
 73				   size_t out_buf_size,
 74				   const char *in_buf);
 75typedef int (debug_prolog_proc_t) (debug_info_t *id,
 76				   struct debug_view *view,
 77				   char *out_buf, size_t out_buf_size);
 78typedef int (debug_input_proc_t) (debug_info_t *id,
 79				  struct debug_view *view,
 80				  struct file *file,
 81				  const char __user *user_buf,
 82				  size_t in_buf_size, loff_t *offset);
 83
 84int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
 85			 int area, debug_entry_t *entry,
 86			 char *out_buf, size_t out_buf_size);
 87
 88#define DEBUG_SPRINTF_MAX_ARGS 10
 89int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
 90			    char *out_buf, size_t out_buf_size,
 91			    const char *inbuf);
 92struct debug_view {
 93	char name[DEBUG_MAX_NAME_LEN];
 94	debug_prolog_proc_t *prolog_proc;
 95	debug_header_proc_t *header_proc;
 96	debug_format_proc_t *format_proc;
 97	debug_input_proc_t  *input_proc;
 98	void		    *private_data;
 99};
100
101extern struct debug_view debug_hex_ascii_view;
102extern struct debug_view debug_sprintf_view;
103
104/* do NOT use the _common functions */
105
106debug_entry_t *debug_event_common(debug_info_t *id, int level,
107				  const void *data, int length);
108
109debug_entry_t *debug_exception_common(debug_info_t *id, int level,
110				      const void *data, int length);
111
112/* Debug Feature API: */
113
114debug_info_t *debug_register(const char *name, int pages, int nr_areas,
115			     int buf_size);
116
117debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas,
118				  int buf_size, umode_t mode, uid_t uid,
119				  gid_t gid);
120
121ssize_t debug_dump(debug_info_t *id, struct debug_view *view,
122		   char *buf, size_t buf_size, bool reverse);
123
124void debug_unregister(debug_info_t *id);
125
126void debug_set_level(debug_info_t *id, int new_level);
127
128void debug_set_critical(void);
129
130void debug_stop_all(void);
131
132/**
133 * debug_level_enabled() - Returns true if debug events for the specified
134 *			   level would be logged. Otherwise returns false.
135 *
136 * @id:		handle for debug log
137 * @level:	debug level
138 *
139 * Return:
140 * - %true if level is less or equal to the current debug level.
141 */
142static inline bool debug_level_enabled(debug_info_t *id, int level)
143{
144	return level <= id->level;
145}
146
147/**
148 * debug_event() - writes binary debug entry to active debug area
149 *		   (if level <= actual debug level)
150 *
151 * @id:		handle for debug log
152 * @level:	debug level
153 * @data:	pointer to data for debug entry
154 * @length:	length of data in bytes
155 *
156 * Return:
157 * - Address of written debug entry
158 * - %NULL if error
159 */
160static inline debug_entry_t *debug_event(debug_info_t *id, int level,
161					 void *data, int length)
162{
163	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
164		return NULL;
165	return debug_event_common(id, level, data, length);
166}
167
168/**
169 * debug_int_event() - writes unsigned integer debug entry to active debug area
170 *		       (if level <= actual debug level)
171 *
172 * @id:		handle for debug log
173 * @level:	debug level
174 * @tag:	integer value for debug entry
175 *
176 * Return:
177 * - Address of written debug entry
178 * - %NULL if error
179 */
180static inline debug_entry_t *debug_int_event(debug_info_t *id, int level,
181					     unsigned int tag)
182{
183	unsigned int t = tag;
184
185	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
186		return NULL;
187	return debug_event_common(id, level, &t, sizeof(unsigned int));
188}
189
190/**
191 * debug_long_event() - writes unsigned long debug entry to active debug area
192 *		       (if level <= actual debug level)
193 *
194 * @id:		handle for debug log
195 * @level:	debug level
196 * @tag:	long integer value for debug entry
197 *
198 * Return:
199 * - Address of written debug entry
200 * - %NULL if error
201 */
202static inline debug_entry_t *debug_long_event(debug_info_t *id, int level,
203					      unsigned long tag)
204{
205	unsigned long t = tag;
206
207	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
208		return NULL;
209	return debug_event_common(id, level, &t, sizeof(unsigned long));
210}
211
212/**
213 * debug_text_event() - writes string debug entry in ascii format to active
214 *			debug area (if level <= actual debug level)
215 *
216 * @id:		handle for debug log
217 * @level:	debug level
218 * @txt:	string for debug entry
219 *
220 * Return:
221 * - Address of written debug entry
222 * - %NULL if error
223 */
224static inline debug_entry_t *debug_text_event(debug_info_t *id, int level,
225					      const char *txt)
226{
227	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
228		return NULL;
229	return debug_event_common(id, level, txt, strlen(txt));
230}
231
232/*
233 * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
234 * stored in the s390dbf. See Documentation/arch/s390/s390dbf.rst for more details!
235 */
236extern debug_entry_t *
237__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
238	__attribute__ ((format(printf, 3, 4)));
239
240/**
241 * debug_sprintf_event() - writes debug entry with format string
242 *			   and varargs (longs) to active debug area
243 *			   (if level $<=$ actual debug level).
244 *
245 * @_id:	handle for debug log
246 * @_level:	debug level
247 * @_fmt:	format string for debug entry
248 * @...:	varargs used as in sprintf()
249 *
250 * Return:
251 * - Address of written debug entry
252 * - %NULL if error
253 *
254 * floats and long long datatypes cannot be used as varargs.
255 */
256#define debug_sprintf_event(_id, _level, _fmt, ...)			\
257({									\
258	debug_entry_t *__ret;						\
259	debug_info_t *__id = _id;					\
260	int __level = _level;						\
261									\
262	if ((!__id) || (__level > __id->level))				\
263		__ret = NULL;						\
264	else								\
265		__ret = __debug_sprintf_event(__id, __level,		\
266					      _fmt, ## __VA_ARGS__);	\
267	__ret;								\
268})
269
270/**
271 * debug_exception() - writes binary debug entry to active debug area
272 *		       (if level <= actual debug level)
273 *		       and switches to next debug area
274 *
275 * @id:		handle for debug log
276 * @level:	debug level
277 * @data:	pointer to data for debug entry
278 * @length:	length of data in bytes
279 *
280 * Return:
281 * - Address of written debug entry
282 * - %NULL if error
283 */
284static inline debug_entry_t *debug_exception(debug_info_t *id, int level,
285					     void *data, int length)
286{
287	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
288		return NULL;
289	return debug_exception_common(id, level, data, length);
290}
291
292/**
293 * debug_int_exception() - writes unsigned int debug entry to active debug area
294 *			   (if level <= actual debug level)
295 *			   and switches to next debug area
296 *
297 * @id:		handle for debug log
298 * @level:	debug level
299 * @tag:	integer value for debug entry
300 *
301 * Return:
302 * - Address of written debug entry
303 * - %NULL if error
304 */
305static inline debug_entry_t *debug_int_exception(debug_info_t *id, int level,
306						 unsigned int tag)
307{
308	unsigned int t = tag;
309
310	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
311		return NULL;
312	return debug_exception_common(id, level, &t, sizeof(unsigned int));
313}
314
315/**
316 * debug_long_exception() - writes long debug entry to active debug area
317 *			   (if level <= actual debug level)
318 *			   and switches to next debug area
319 *
320 * @id:		handle for debug log
321 * @level:	debug level
322 * @tag:	long integer value for debug entry
323 *
324 * Return:
325 * - Address of written debug entry
326 * - %NULL if error
327 */
328static inline debug_entry_t *debug_long_exception (debug_info_t *id, int level,
329						   unsigned long tag)
330{
331	unsigned long t = tag;
332
333	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
334		return NULL;
335	return debug_exception_common(id, level, &t, sizeof(unsigned long));
336}
337
338/**
339 * debug_text_exception() - writes string debug entry in ascii format to active
340 *			    debug area (if level <= actual debug level)
341 *			    and switches to next debug area
342 * area
343 *
344 * @id:	handle for debug log
345 * @level:	debug level
346 * @txt:	string for debug entry
347 *
348 * Return:
349 * - Address of written debug entry
350 * - %NULL if error
351 */
352static inline debug_entry_t *debug_text_exception(debug_info_t *id, int level,
353						  const char *txt)
354{
355	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
356		return NULL;
357	return debug_exception_common(id, level, txt, strlen(txt));
358}
359
360/*
361 * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
362 * stored in the s390dbf. See Documentation/arch/s390/s390dbf.rst for more details!
363 */
364extern debug_entry_t *
365__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
366	__attribute__ ((format(printf, 3, 4)));
367
368
369/**
370 * debug_sprintf_exception() - writes debug entry with format string and
371 *			       varargs (longs) to active debug area
372 *			       (if level <= actual debug level)
373 *			       and switches to next debug area.
374 *
375 * @_id:	handle for debug log
376 * @_level:	debug level
377 * @_fmt:	format string for debug entry
378 * @...:	varargs used as in sprintf()
379 *
380 * Return:
381 * - Address of written debug entry
382 * - %NULL if error
383 *
384 * floats and long long datatypes cannot be used as varargs.
385 */
386#define debug_sprintf_exception(_id, _level, _fmt, ...)			\
387({									\
388	debug_entry_t *__ret;						\
389	debug_info_t *__id = _id;					\
390	int __level = _level;						\
391									\
392	if ((!__id) || (__level > __id->level))				\
393		__ret = NULL;						\
394	else								\
395		__ret = __debug_sprintf_exception(__id, __level,	\
396						  _fmt, ## __VA_ARGS__);\
397	__ret;								\
398})
399
400int debug_register_view(debug_info_t *id, struct debug_view *view);
401
402int debug_unregister_view(debug_info_t *id, struct debug_view *view);
403
404#ifndef MODULE
405
406/*
407 * Note: Initial page and area numbers must be fixed to allow static
408 * initialization. This enables very early tracing. Changes to these values
409 * must be reflected in __DEFINE_STATIC_AREA.
410 */
411#define EARLY_PAGES		8
412#define EARLY_AREAS		1
413
414#define VNAME(var, suffix)	__##var##_##suffix
415
416/*
417 * Define static areas for early trace data. During boot debug_register_static()
418 * will replace these with dynamically allocated areas to allow custom page and
419 * area sizes, and dynamic resizing.
420 */
421#define __DEFINE_STATIC_AREA(var)					\
422static char VNAME(var, data)[EARLY_PAGES][PAGE_SIZE] __initdata;	\
423static debug_entry_t *VNAME(var, pages)[EARLY_PAGES] __initdata = {	\
424	(debug_entry_t *)VNAME(var, data)[0],				\
425	(debug_entry_t *)VNAME(var, data)[1],				\
426	(debug_entry_t *)VNAME(var, data)[2],				\
427	(debug_entry_t *)VNAME(var, data)[3],				\
428	(debug_entry_t *)VNAME(var, data)[4],				\
429	(debug_entry_t *)VNAME(var, data)[5],				\
430	(debug_entry_t *)VNAME(var, data)[6],				\
431	(debug_entry_t *)VNAME(var, data)[7],				\
432};									\
433static debug_entry_t **VNAME(var, areas)[EARLY_AREAS] __initdata = {	\
434	(debug_entry_t **)VNAME(var, pages),				\
435};									\
436static int VNAME(var, active_pages)[EARLY_AREAS] __initdata;		\
437static int VNAME(var, active_entries)[EARLY_AREAS] __initdata
438
439#define __DEBUG_INFO_INIT(var, _name, _buf_size) {			\
440	.next = NULL,							\
441	.prev = NULL,							\
442	.ref_count = REFCOUNT_INIT(1),					\
443	.lock = __SPIN_LOCK_UNLOCKED(var.lock),				\
444	.level = DEBUG_DEFAULT_LEVEL,					\
445	.nr_areas = EARLY_AREAS,					\
446	.pages_per_area = EARLY_PAGES,					\
447	.buf_size = (_buf_size),					\
448	.entry_size = sizeof(debug_entry_t) + (_buf_size),		\
449	.areas = VNAME(var, areas),					\
450	.active_area = 0,						\
451	.active_pages = VNAME(var, active_pages),			\
452	.active_entries = VNAME(var, active_entries),			\
453	.debugfs_root_entry = NULL,					\
454	.debugfs_entries = { NULL },					\
455	.views = { NULL },						\
456	.name = (_name),						\
457	.mode = 0600,							\
458}
459
460#define __REGISTER_STATIC_DEBUG_INFO(var, name, pages, areas, view)	\
461static int __init VNAME(var, reg)(void)					\
462{									\
463	debug_register_static(&var, (pages), (areas));			\
464	debug_register_view(&var, (view));				\
465	return 0;							\
466}									\
467arch_initcall(VNAME(var, reg))
468
469/**
470 * DEFINE_STATIC_DEBUG_INFO - Define static debug_info_t
471 *
472 * @var: Name of debug_info_t variable
473 * @name: Name of debug log (e.g. used for debugfs entry)
474 * @pages: Number of pages per area
475 * @nr_areas: Number of debug areas
476 * @buf_size: Size of data area in each debug entry
477 * @view: Pointer to debug view struct
478 *
479 * Define a static debug_info_t for early tracing. The associated debugfs log
480 * is automatically registered with the specified debug view.
481 *
482 * Important: Users of this macro must not call any of the
483 * debug_register/_unregister() functions for this debug_info_t!
484 *
485 * Note: Tracing will start with a fixed number of initial pages and areas.
486 * The debug area will be changed to use the specified numbers during
487 * arch_initcall.
488 */
489#define DEFINE_STATIC_DEBUG_INFO(var, name, pages, nr_areas, buf_size, view) \
490__DEFINE_STATIC_AREA(var);						\
491static debug_info_t __refdata var =					\
492	__DEBUG_INFO_INIT(var, (name), (buf_size));			\
493__REGISTER_STATIC_DEBUG_INFO(var, name, pages, nr_areas, view)
494
495void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas);
496
497#endif /* MODULE */
498
499#endif /* _ASM_S390_DEBUG_H */
~/ Read-only file preview.