1265236Sken/* SPDX-License-Identifier: GPL-2.0 */
2265236Sken/*
3283661Sslm *   S/390 debug facility
4299265Sslm *
5265236Sken *    Copyright IBM Corp. 1999, 2020
6265236Sken */
7265236Sken#ifndef _ASM_S390_DEBUG_H
8265236Sken#define _ASM_S390_DEBUG_H
9265236Sken
10265236Sken#include <linux/string.h>
11265236Sken#include <linux/spinlock.h>
12265236Sken#include <linux/kernel.h>
13265236Sken#include <linux/time.h>
14265236Sken#include <linux/refcount.h>
15265236Sken#include <linux/fs.h>
16265236Sken#include <linux/init.h>
17265236Sken
18265236Sken#define DEBUG_MAX_LEVEL		   6  /* debug levels range from 0 to 6 */
19265236Sken#define DEBUG_OFF_LEVEL		   -1 /* level where debug is switched off */
20265236Sken#define DEBUG_FLUSH_ALL		   -1 /* parameter to flush all areas */
21265236Sken#define DEBUG_MAX_VIEWS		   10 /* max number of views in proc fs */
22265236Sken#define DEBUG_MAX_NAME_LEN	   64 /* max length for a debugfs file name */
23265236Sken#define DEBUG_DEFAULT_LEVEL	   3  /* initial debug level */
24265236Sken
25265236Sken#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
26265236Sken
27283661Sslm#define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */
28283661Sslm					      /* the entry information */
29283661Sslm
30265236Sken#define __DEBUG_FEATURE_VERSION	   3  /* version of debug feature */
31265236Sken
32265236Skenstruct __debug_entry {
33265236Sken	unsigned long clock	: 60;
34265236Sken	unsigned long exception	:  1;
35283661Sslm	unsigned long level	:  3;
36265236Sken	void *caller;
37265236Sken	unsigned short cpu;
38265236Sken} __packed;
39265236Sken
40265236Skentypedef struct __debug_entry debug_entry_t;
41265236Sken
42265236Skenstruct debug_view;
43265236Sken
44265236Skentypedef struct debug_info {
45265236Sken	struct debug_info *next;
46265236Sken	struct debug_info *prev;
47265236Sken	refcount_t ref_count;
48265236Sken	spinlock_t lock;
49265236Sken	int level;
50265236Sken	int nr_areas;
51265236Sken	int pages_per_area;
52265236Sken	int buf_size;
53265236Sken	int entry_size;
54265236Sken	debug_entry_t ***areas;
55265236Sken	int active_area;
56265236Sken	int *active_pages;
57265236Sken	int *active_entries;
58265236Sken	struct dentry *debugfs_root_entry;
59265236Sken	struct dentry *debugfs_entries[DEBUG_MAX_VIEWS];
60265236Sken	struct debug_view *views[DEBUG_MAX_VIEWS];
61265236Sken	char name[DEBUG_MAX_NAME_LEN];
62265236Sken	umode_t mode;
63265236Sken} debug_info_t;
64265236Sken
65265236Skentypedef int (debug_header_proc_t) (debug_info_t *id,
66265236Sken				   struct debug_view *view,
67265236Sken				   int area,
68265236Sken				   debug_entry_t *entry,
69265236Sken				   char *out_buf);
70265236Sken
71265236Skentypedef int (debug_format_proc_t) (debug_info_t *id,
72265236Sken				   struct debug_view *view, char *out_buf,
73265236Sken				   const char *in_buf);
74265236Skentypedef int (debug_prolog_proc_t) (debug_info_t *id,
75319435Sslm				   struct debug_view *view,
76319435Sslm				   char *out_buf);
77265236Skentypedef int (debug_input_proc_t) (debug_info_t *id,
78265236Sken				  struct debug_view *view,
79265236Sken				  struct file *file,
80265236Sken				  const char __user *user_buf,
81319435Sslm				  size_t in_buf_size, loff_t *offset);
82265236Sken
83265236Skenint debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
84265236Sken			 int area, debug_entry_t *entry, char *out_buf);
85265236Sken
86265236Skenstruct debug_view {
87265236Sken	char name[DEBUG_MAX_NAME_LEN];
88265236Sken	debug_prolog_proc_t *prolog_proc;
89265236Sken	debug_header_proc_t *header_proc;
90265236Sken	debug_format_proc_t *format_proc;
91265236Sken	debug_input_proc_t  *input_proc;
92265236Sken	void		    *private_data;
93265236Sken};
94265236Sken
95265236Skenextern struct debug_view debug_hex_ascii_view;
96265236Skenextern struct debug_view debug_sprintf_view;
97265236Sken
98265236Sken/* do NOT use the _common functions */
99265236Sken
100265236Skendebug_entry_t *debug_event_common(debug_info_t *id, int level,
101265236Sken				  const void *data, int length);
102265236Sken
103265236Skendebug_entry_t *debug_exception_common(debug_info_t *id, int level,
104265236Sken				      const void *data, int length);
105265236Sken
106265236Sken/* Debug Feature API: */
107265236Sken
108265236Skendebug_info_t *debug_register(const char *name, int pages, int nr_areas,
109265236Sken			     int buf_size);
110265236Sken
111265236Skendebug_info_t *debug_register_mode(const char *name, int pages, int nr_areas,
112265236Sken				  int buf_size, umode_t mode, uid_t uid,
113265236Sken				  gid_t gid);
114265236Sken
115265236Skenvoid debug_unregister(debug_info_t *id);
116265236Sken
117265236Skenvoid debug_set_level(debug_info_t *id, int new_level);
118265236Sken
119265236Skenvoid debug_set_critical(void);
120265236Sken
121265236Skenvoid debug_stop_all(void);
122265236Sken
123265236Sken/**
124265236Sken * debug_level_enabled() - Returns true if debug events for the specified
125299265Sslm *			   level would be logged. Otherwise returns false.
126265236Sken *
127265236Sken * @id:		handle for debug log
128265236Sken * @level:	debug level
129299265Sslm *
130283661Sslm * Return:
131265236Sken * - %true if level is less or equal to the current debug level.
132265236Sken */
133265236Skenstatic inline bool debug_level_enabled(debug_info_t *id, int level)
134265236Sken{
135265236Sken	return level <= id->level;
136265236Sken}
137265236Sken
138265236Sken/**
139265236Sken * debug_event() - writes binary debug entry to active debug area
140265236Sken *		   (if level <= actual debug level)
141265236Sken *
142265236Sken * @id:		handle for debug log
143265236Sken * @level:	debug level
144265236Sken * @data:	pointer to data for debug entry
145265236Sken * @length:	length of data in bytes
146299265Sslm *
147299265Sslm * Return:
148299265Sslm * - Address of written debug entry
149283661Sslm * - %NULL if error
150283661Sslm */
151265236Skenstatic inline debug_entry_t *debug_event(debug_info_t *id, int level,
152265236Sken					 void *data, int length)
153265236Sken{
154265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
155265236Sken		return NULL;
156265236Sken	return debug_event_common(id, level, data, length);
157265236Sken}
158265236Sken
159265236Sken/**
160265236Sken * debug_int_event() - writes unsigned integer debug entry to active debug area
161265236Sken *		       (if level <= actual debug level)
162265236Sken *
163265236Sken * @id:		handle for debug log
164265236Sken * @level:	debug level
165265236Sken * @tag:	integer value for debug entry
166265236Sken *
167265236Sken * Return:
168265236Sken * - Address of written debug entry
169265236Sken * - %NULL if error
170265236Sken */
171265236Skenstatic inline debug_entry_t *debug_int_event(debug_info_t *id, int level,
172265236Sken					     unsigned int tag)
173265236Sken{
174265236Sken	unsigned int t = tag;
175265236Sken
176265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
177265236Sken		return NULL;
178265236Sken	return debug_event_common(id, level, &t, sizeof(unsigned int));
179265236Sken}
180265236Sken
181265236Sken/**
182265236Sken * debug_long_event() - writes unsigned long debug entry to active debug area
183265236Sken *		       (if level <= actual debug level)
184265236Sken *
185265712Sken * @id:		handle for debug log
186265712Sken * @level:	debug level
187265236Sken * @tag:	long integer value for debug entry
188265236Sken *
189265236Sken * Return:
190265236Sken * - Address of written debug entry
191265236Sken * - %NULL if error
192265236Sken */
193265236Skenstatic inline debug_entry_t *debug_long_event(debug_info_t *id, int level,
194265236Sken					      unsigned long tag)
195265236Sken{
196265236Sken	unsigned long t = tag;
197265236Sken
198265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
199265236Sken		return NULL;
200265236Sken	return debug_event_common(id, level, &t, sizeof(unsigned long));
201265236Sken}
202265236Sken
203265236Sken/**
204265236Sken * debug_text_event() - writes string debug entry in ascii format to active
205265236Sken *			debug area (if level <= actual debug level)
206265236Sken *
207265236Sken * @id:		handle for debug log
208265236Sken * @level:	debug level
209265236Sken * @txt:	string for debug entry
210265236Sken *
211265236Sken * Return:
212265236Sken * - Address of written debug entry
213265236Sken * - %NULL if error
214265236Sken */
215265236Skenstatic inline debug_entry_t *debug_text_event(debug_info_t *id, int level,
216265236Sken					      const char *txt)
217265236Sken{
218265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
219265236Sken		return NULL;
220265712Sken	return debug_event_common(id, level, txt, strlen(txt));
221265712Sken}
222265236Sken
223265236Sken/*
224265236Sken * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
225265236Sken * stored in the s390dbf. See Documentation/arch/s390/s390dbf.rst for more details!
226265236Sken */
227265236Skenextern debug_entry_t *
228265236Sken__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
229265236Sken	__attribute__ ((format(printf, 3, 4)));
230265236Sken
231265236Sken/**
232283661Sslm * debug_sprintf_event() - writes debug entry with format string
233265236Sken *			   and varargs (longs) to active debug area
234265236Sken *			   (if level $<=$ actual debug level).
235265236Sken *
236265236Sken * @_id:	handle for debug log
237265236Sken * @_level:	debug level
238265236Sken * @_fmt:	format string for debug entry
239265236Sken * @...:	varargs used as in sprintf()
240265236Sken *
241265236Sken * Return:
242265236Sken * - Address of written debug entry
243265236Sken * - %NULL if error
244265236Sken *
245265236Sken * floats and long long datatypes cannot be used as varargs.
246265236Sken */
247265236Sken#define debug_sprintf_event(_id, _level, _fmt, ...)			\
248265236Sken({									\
249299269Sslm	debug_entry_t *__ret;						\
250299269Sslm	debug_info_t *__id = _id;					\
251283661Sslm	int __level = _level;						\
252265236Sken									\
253265236Sken	if ((!__id) || (__level > __id->level))				\
254265236Sken		__ret = NULL;						\
255283661Sslm	else								\
256283661Sslm		__ret = __debug_sprintf_event(__id, __level,		\
257283661Sslm					      _fmt, ## __VA_ARGS__);	\
258283661Sslm	__ret;								\
259265236Sken})
260283661Sslm
261283661Sslm/**
262299269Sslm * debug_exception() - writes binary debug entry to active debug area
263265236Sken *		       (if level <= actual debug level)
264283661Sslm *		       and switches to next debug area
265283661Sslm *
266299269Sslm * @id:		handle for debug log
267283661Sslm * @level:	debug level
268283661Sslm * @data:	pointer to data for debug entry
269283661Sslm * @length:	length of data in bytes
270283661Sslm *
271265236Sken * Return:
272265236Sken * - Address of written debug entry
273265236Sken * - %NULL if error
274265236Sken */
275265236Skenstatic inline debug_entry_t *debug_exception(debug_info_t *id, int level,
276265236Sken					     void *data, int length)
277265236Sken{
278265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
279265236Sken		return NULL;
280265236Sken	return debug_exception_common(id, level, data, length);
281265236Sken}
282265236Sken
283265236Sken/**
284265236Sken * debug_int_exception() - writes unsigned int debug entry to active debug area
285265236Sken *			   (if level <= actual debug level)
286265236Sken *			   and switches to next debug area
287265236Sken *
288265236Sken * @id:		handle for debug log
289265236Sken * @level:	debug level
290265236Sken * @tag:	integer value for debug entry
291265236Sken *
292265236Sken * Return:
293265236Sken * - Address of written debug entry
294265236Sken * - %NULL if error
295265236Sken */
296265236Skenstatic inline debug_entry_t *debug_int_exception(debug_info_t *id, int level,
297265236Sken						 unsigned int tag)
298265236Sken{
299283661Sslm	unsigned int t = tag;
300283661Sslm
301265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
302265236Sken		return NULL;
303265236Sken	return debug_exception_common(id, level, &t, sizeof(unsigned int));
304265236Sken}
305265236Sken
306265236Sken/**
307265236Sken * debug_long_exception() - writes long debug entry to active debug area
308265236Sken *			   (if level <= actual debug level)
309265236Sken *			   and switches to next debug area
310265236Sken *
311265236Sken * @id:		handle for debug log
312265236Sken * @level:	debug level
313265236Sken * @tag:	long integer value for debug entry
314265236Sken *
315265236Sken * Return:
316265236Sken * - Address of written debug entry
317265236Sken * - %NULL if error
318265236Sken */
319265236Skenstatic inline debug_entry_t *debug_long_exception (debug_info_t *id, int level,
320359359Smav						   unsigned long tag)
321265236Sken{
322265236Sken	unsigned long t = tag;
323265236Sken
324265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
325265236Sken		return NULL;
326265236Sken	return debug_exception_common(id, level, &t, sizeof(unsigned long));
327265236Sken}
328265236Sken
329265236Sken/**
330265236Sken * debug_text_exception() - writes string debug entry in ascii format to active
331265236Sken *			    debug area (if level <= actual debug level)
332265236Sken *			    and switches to next debug area
333265236Sken * area
334265236Sken *
335265236Sken * @id:	handle for debug log
336265236Sken * @level:	debug level
337265236Sken * @txt:	string for debug entry
338265236Sken *
339265236Sken * Return:
340265236Sken * - Address of written debug entry
341265236Sken * - %NULL if error
342265236Sken */
343265236Skenstatic inline debug_entry_t *debug_text_exception(debug_info_t *id, int level,
344265236Sken						  const char *txt)
345265236Sken{
346265236Sken	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
347265236Sken		return NULL;
348265236Sken	return debug_exception_common(id, level, txt, strlen(txt));
349265236Sken}
350265236Sken
351265236Sken/*
352265236Sken * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are
353265236Sken * stored in the s390dbf. See Documentation/arch/s390/s390dbf.rst for more details!
354265236Sken */
355319435Sslmextern debug_entry_t *
356265236Sken__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
357265236Sken	__attribute__ ((format(printf, 3, 4)));
358265236Sken
359265236Sken
360265236Sken/**
361265236Sken * debug_sprintf_exception() - writes debug entry with format string and
362265236Sken *			       varargs (longs) to active debug area
363265236Sken *			       (if level <= actual debug level)
364265236Sken *			       and switches to next debug area.
365265236Sken *
366265236Sken * @_id:	handle for debug log
367265236Sken * @_level:	debug level
368265236Sken * @_fmt:	format string for debug entry
369265236Sken * @...:	varargs used as in sprintf()
370265236Sken *
371265236Sken * Return:
372265236Sken * - Address of written debug entry
373265236Sken * - %NULL if error
374265236Sken *
375265236Sken * floats and long long datatypes cannot be used as varargs.
376265236Sken */
377265236Sken#define debug_sprintf_exception(_id, _level, _fmt, ...)			\
378265236Sken({									\
379265236Sken	debug_entry_t *__ret;						\
380265236Sken	debug_info_t *__id = _id;					\
381299267Sslm	int __level = _level;						\
382299267Sslm									\
383299274Sslm	if ((!__id) || (__level > __id->level))				\
384299267Sslm		__ret = NULL;						\
385265236Sken	else								\
386265236Sken		__ret = __debug_sprintf_exception(__id, __level,	\
387265236Sken						  _fmt, ## __VA_ARGS__);\
388299267Sslm	__ret;								\
389265236Sken})
390265236Sken
391265236Skenint debug_register_view(debug_info_t *id, struct debug_view *view);
392265236Sken
393265236Skenint debug_unregister_view(debug_info_t *id, struct debug_view *view);
394265236Sken
395265236Sken#ifndef MODULE
396265236Sken
397265236Sken/*
398265236Sken * Note: Initial page and area numbers must be fixed to allow static
399265236Sken * initialization. This enables very early tracing. Changes to these values
400265236Sken * must be reflected in __DEFINE_STATIC_AREA.
401299267Sslm */
402299267Sslm#define EARLY_PAGES		8
403265236Sken#define EARLY_AREAS		1
404265236Sken
405265236Sken#define VNAME(var, suffix)	__##var##_##suffix
406265236Sken
407265236Sken/*
408265236Sken * Define static areas for early trace data. During boot debug_register_static()
409265236Sken * will replace these with dynamically allocated areas to allow custom page and
410265236Sken * area sizes, and dynamic resizing.
411265236Sken */
412265236Sken#define __DEFINE_STATIC_AREA(var)					\
413265236Skenstatic char VNAME(var, data)[EARLY_PAGES][PAGE_SIZE] __initdata;	\
414265236Skenstatic debug_entry_t *VNAME(var, pages)[EARLY_PAGES] __initdata = {	\
415265236Sken	(debug_entry_t *)VNAME(var, data)[0],				\
416265236Sken	(debug_entry_t *)VNAME(var, data)[1],				\
417265236Sken	(debug_entry_t *)VNAME(var, data)[2],				\
418265236Sken	(debug_entry_t *)VNAME(var, data)[3],				\
419265236Sken	(debug_entry_t *)VNAME(var, data)[4],				\
420265236Sken	(debug_entry_t *)VNAME(var, data)[5],				\
421265236Sken	(debug_entry_t *)VNAME(var, data)[6],				\
422265236Sken	(debug_entry_t *)VNAME(var, data)[7],				\
423265236Sken};									\
424265236Skenstatic debug_entry_t **VNAME(var, areas)[EARLY_AREAS] __initdata = {	\
425265236Sken	(debug_entry_t **)VNAME(var, pages),				\
426265236Sken};									\
427265236Skenstatic int VNAME(var, active_pages)[EARLY_AREAS] __initdata;		\
428265236Skenstatic int VNAME(var, active_entries)[EARLY_AREAS] __initdata
429265236Sken
430265236Sken#define __DEBUG_INFO_INIT(var, _name, _buf_size) {			\
431265236Sken	.next = NULL,							\
432265236Sken	.prev = NULL,							\
433265236Sken	.ref_count = REFCOUNT_INIT(1),					\
434265236Sken	.lock = __SPIN_LOCK_UNLOCKED(var.lock),				\
435265236Sken	.level = DEBUG_DEFAULT_LEVEL,					\
436265236Sken	.nr_areas = EARLY_AREAS,					\
437265236Sken	.pages_per_area = EARLY_PAGES,					\
438265236Sken	.buf_size = (_buf_size),					\
439265236Sken	.entry_size = sizeof(debug_entry_t) + (_buf_size),		\
440265236Sken	.areas = VNAME(var, areas),					\
441265236Sken	.active_area = 0,						\
442265236Sken	.active_pages = VNAME(var, active_pages),			\
443265236Sken	.active_entries = VNAME(var, active_entries),			\
444265236Sken	.debugfs_root_entry = NULL,					\
445265236Sken	.debugfs_entries = { NULL },					\
446265236Sken	.views = { NULL },						\
447265236Sken	.name = (_name),						\
448265236Sken	.mode = 0600,							\
449265236Sken}
450265236Sken
451265236Sken#define __REGISTER_STATIC_DEBUG_INFO(var, name, pages, areas, view)	\
452265236Skenstatic int __init VNAME(var, reg)(void)					\
453265236Sken{									\
454265236Sken	debug_register_static(&var, (pages), (areas));			\
455265236Sken	debug_register_view(&var, (view));				\
456265236Sken	return 0;							\
457265236Sken}									\
458265236Skenarch_initcall(VNAME(var, reg))
459265236Sken
460265236Sken/**
461265236Sken * DEFINE_STATIC_DEBUG_INFO - Define static debug_info_t
462265236Sken *
463265236Sken * @var: Name of debug_info_t variable
464265236Sken * @name: Name of debug log (e.g. used for debugfs entry)
465265236Sken * @pages: Number of pages per area
466265236Sken * @nr_areas: Number of debug areas
467265236Sken * @buf_size: Size of data area in each debug entry
468265236Sken * @view: Pointer to debug view struct
469265236Sken *
470265236Sken * Define a static debug_info_t for early tracing. The associated debugfs log
471265236Sken * is automatically registered with the specified debug view.
472265236Sken *
473265236Sken * Important: Users of this macro must not call any of the
474283661Sslm * debug_register/_unregister() functions for this debug_info_t!
475283661Sslm *
476283661Sslm * Note: Tracing will start with a fixed number of initial pages and areas.
477283661Sslm * The debug area will be changed to use the specified numbers during
478283661Sslm * arch_initcall.
479265236Sken */
480265236Sken#define DEFINE_STATIC_DEBUG_INFO(var, name, pages, nr_areas, buf_size, view) \
481265236Sken__DEFINE_STATIC_AREA(var);						\
482265236Skenstatic debug_info_t __refdata var =					\
483319435Sslm	__DEBUG_INFO_INIT(var, (name), (buf_size));			\
484319435Sslm__REGISTER_STATIC_DEBUG_INFO(var, name, pages, nr_areas, view)
485319435Sslm
486319435Sslmvoid debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas);
487319435Sslm
488319435Sslm#endif /* MODULE */
489319435Sslm
490265236Sken#endif /* _ASM_S390_DEBUG_H */
491265236Sken