]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
1da177e4 | 2 | /* |
1da177e4 LT |
3 | * S/390 debug facility |
4 | * | |
a53c8fab | 5 | * Copyright IBM Corp. 1999, 2000 |
1da177e4 | 6 | */ |
1da177e4 LT |
7 | #ifndef DEBUG_H |
8 | #define DEBUG_H | |
9 | ||
124b51c7 | 10 | #include <linux/string.h> |
1da177e4 LT |
11 | #include <linux/spinlock.h> |
12 | #include <linux/kernel.h> | |
13 | #include <linux/time.h> | |
efc0c21c | 14 | #include <linux/refcount.h> |
9807f759 | 15 | #include <uapi/asm/debug.h> |
1da177e4 | 16 | |
496da0d7 HC |
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 */ | |
1da177e4 LT |
23 | |
24 | #define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */ | |
25 | ||
496da0d7 HC |
26 | #define DEBUG_DATA(entry) (char *)(entry + 1) /* data is stored behind */ |
27 | /* the entry information */ | |
1da177e4 | 28 | |
1da177e4 LT |
29 | typedef struct __debug_entry debug_entry_t; |
30 | ||
31 | struct debug_view; | |
32 | ||
496da0d7 HC |
33 | typedef struct debug_info { |
34 | struct debug_info *next; | |
35 | struct debug_info *prev; | |
efc0c21c | 36 | refcount_t ref_count; |
496da0d7 | 37 | spinlock_t lock; |
1da177e4 LT |
38 | int level; |
39 | int nr_areas; | |
66a464db | 40 | int pages_per_area; |
1da177e4 | 41 | int buf_size; |
496da0d7 HC |
42 | int entry_size; |
43 | debug_entry_t ***areas; | |
1da177e4 | 44 | int active_area; |
66a464db MH |
45 | int *active_pages; |
46 | int *active_entries; | |
496da0d7 HC |
47 | struct dentry *debugfs_root_entry; |
48 | struct dentry *debugfs_entries[DEBUG_MAX_VIEWS]; | |
49 | struct debug_view *views[DEBUG_MAX_VIEWS]; | |
66a464db | 50 | char name[DEBUG_MAX_NAME_LEN]; |
f4ae40a6 | 51 | umode_t mode; |
1da177e4 LT |
52 | } debug_info_t; |
53 | ||
496da0d7 HC |
54 | typedef int (debug_header_proc_t) (debug_info_t *id, |
55 | struct debug_view *view, | |
1da177e4 | 56 | int area, |
496da0d7 HC |
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, | |
1da177e4 | 69 | const char __user *user_buf, |
496da0d7 HC |
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); | |
1da177e4 | 74 | |
1da177e4 | 75 | struct debug_view { |
66a464db | 76 | char name[DEBUG_MAX_NAME_LEN]; |
496da0d7 HC |
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; | |
1da177e4 LT |
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 | ||
496da0d7 HC |
90 | debug_entry_t *debug_event_common(debug_info_t *id, int level, |
91 | const void *data, int length); | |
1da177e4 | 92 | |
496da0d7 HC |
93 | debug_entry_t *debug_exception_common(debug_info_t *id, int level, |
94 | const void *data, int length); | |
1da177e4 LT |
95 | |
96 | /* Debug Feature API: */ | |
97 | ||
5cbbf16a | 98 | debug_info_t *debug_register(const char *name, int pages, int nr_areas, |
496da0d7 | 99 | int buf_size); |
1da177e4 | 100 | |
5cbbf16a | 101 | debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas, |
f4ae40a6 | 102 | int buf_size, umode_t mode, uid_t uid, |
9637c3f3 MH |
103 | gid_t gid); |
104 | ||
496da0d7 | 105 | void debug_unregister(debug_info_t *id); |
1da177e4 | 106 | |
496da0d7 | 107 | void debug_set_level(debug_info_t *id, int new_level); |
1da177e4 | 108 | |
3ab121ab | 109 | void debug_set_critical(void); |
1da177e4 LT |
110 | void debug_stop_all(void); |
111 | ||
496da0d7 | 112 | static inline bool debug_level_enabled(debug_info_t *id, int level) |
f1d86b61 HB |
113 | { |
114 | return level <= id->level; | |
115 | } | |
116 | ||
496da0d7 HC |
117 | static inline debug_entry_t *debug_event(debug_info_t *id, int level, |
118 | void *data, int length) | |
1da177e4 | 119 | { |
66a464db MH |
120 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
121 | return NULL; | |
496da0d7 | 122 | return debug_event_common(id, level, data, length); |
1da177e4 LT |
123 | } |
124 | ||
496da0d7 HC |
125 | static inline debug_entry_t *debug_int_event(debug_info_t *id, int level, |
126 | unsigned int tag) | |
1da177e4 | 127 | { |
496da0d7 HC |
128 | unsigned int t = tag; |
129 | ||
66a464db MH |
130 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
131 | return NULL; | |
496da0d7 | 132 | return debug_event_common(id, level, &t, sizeof(unsigned int)); |
1da177e4 LT |
133 | } |
134 | ||
496da0d7 HC |
135 | static inline debug_entry_t *debug_long_event(debug_info_t *id, int level, |
136 | unsigned long tag) | |
1da177e4 | 137 | { |
496da0d7 HC |
138 | unsigned long t = tag; |
139 | ||
66a464db MH |
140 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
141 | return NULL; | |
496da0d7 | 142 | return debug_event_common(id, level, &t, sizeof(unsigned long)); |
1da177e4 LT |
143 | } |
144 | ||
496da0d7 HC |
145 | static inline debug_entry_t *debug_text_event(debug_info_t *id, int level, |
146 | const char *txt) | |
1da177e4 | 147 | { |
66a464db MH |
148 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
149 | return NULL; | |
496da0d7 | 150 | return debug_event_common(id, level, txt, strlen(txt)); |
1da177e4 LT |
151 | } |
152 | ||
f64d04c0 MH |
153 | /* |
154 | * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are | |
155 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! | |
156 | */ | |
1da177e4 | 157 | extern debug_entry_t * |
832a7710 | 158 | __debug_sprintf_event(debug_info_t *id, int level, char *string, ...) |
1da177e4 LT |
159 | __attribute__ ((format(printf, 3, 4))); |
160 | ||
832a7710 CB |
161 | #define debug_sprintf_event(_id, _level, _fmt, ...) \ |
162 | ({ \ | |
163 | debug_entry_t *__ret; \ | |
164 | debug_info_t *__id = _id; \ | |
165 | int __level = _level; \ | |
496da0d7 | 166 | \ |
832a7710 CB |
167 | if ((!__id) || (__level > __id->level)) \ |
168 | __ret = NULL; \ | |
169 | else \ | |
170 | __ret = __debug_sprintf_event(__id, __level, \ | |
171 | _fmt, ## __VA_ARGS__); \ | |
172 | __ret; \ | |
173 | }) | |
1da177e4 | 174 | |
496da0d7 HC |
175 | static inline debug_entry_t *debug_exception(debug_info_t *id, int level, |
176 | void *data, int length) | |
1da177e4 | 177 | { |
66a464db MH |
178 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
179 | return NULL; | |
496da0d7 | 180 | return debug_exception_common(id, level, data, length); |
1da177e4 LT |
181 | } |
182 | ||
496da0d7 HC |
183 | static inline debug_entry_t *debug_int_exception(debug_info_t *id, int level, |
184 | unsigned int tag) | |
1da177e4 | 185 | { |
496da0d7 HC |
186 | unsigned int t = tag; |
187 | ||
66a464db MH |
188 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
189 | return NULL; | |
496da0d7 | 190 | return debug_exception_common(id, level, &t, sizeof(unsigned int)); |
1da177e4 LT |
191 | } |
192 | ||
496da0d7 HC |
193 | static inline debug_entry_t *debug_long_exception (debug_info_t *id, int level, |
194 | unsigned long tag) | |
1da177e4 | 195 | { |
496da0d7 HC |
196 | unsigned long t = tag; |
197 | ||
66a464db MH |
198 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
199 | return NULL; | |
496da0d7 | 200 | return debug_exception_common(id, level, &t, sizeof(unsigned long)); |
1da177e4 LT |
201 | } |
202 | ||
496da0d7 HC |
203 | static inline debug_entry_t *debug_text_exception(debug_info_t *id, int level, |
204 | const char *txt) | |
1da177e4 | 205 | { |
66a464db MH |
206 | if ((!id) || (level > id->level) || (id->pages_per_area == 0)) |
207 | return NULL; | |
496da0d7 | 208 | return debug_exception_common(id, level, txt, strlen(txt)); |
1da177e4 LT |
209 | } |
210 | ||
f64d04c0 MH |
211 | /* |
212 | * IMPORTANT: Use "%s" in sprintf format strings with care! Only pointers are | |
213 | * stored in the s390dbf. See Documentation/s390/s390dbf.txt for more details! | |
214 | */ | |
1da177e4 | 215 | extern debug_entry_t * |
832a7710 | 216 | __debug_sprintf_exception(debug_info_t *id, int level, char *string, ...) |
1da177e4 LT |
217 | __attribute__ ((format(printf, 3, 4))); |
218 | ||
832a7710 CB |
219 | #define debug_sprintf_exception(_id, _level, _fmt, ...) \ |
220 | ({ \ | |
221 | debug_entry_t *__ret; \ | |
222 | debug_info_t *__id = _id; \ | |
223 | int __level = _level; \ | |
496da0d7 | 224 | \ |
832a7710 CB |
225 | if ((!__id) || (__level > __id->level)) \ |
226 | __ret = NULL; \ | |
227 | else \ | |
228 | __ret = __debug_sprintf_exception(__id, __level, \ | |
229 | _fmt, ## __VA_ARGS__);\ | |
230 | __ret; \ | |
231 | }) | |
232 | ||
496da0d7 HC |
233 | int debug_register_view(debug_info_t *id, struct debug_view *view); |
234 | int debug_unregister_view(debug_info_t *id, struct debug_view *view); | |
1da177e4 LT |
235 | |
236 | /* | |
237 | define the debug levels: | |
238 | - 0 No debugging output to console or syslog | |
496da0d7 | 239 | - 1 Log internal errors to syslog, ignore check conditions |
1da177e4 LT |
240 | - 2 Log internal errors and check conditions to syslog |
241 | - 3 Log internal errors to console, log check conditions to syslog | |
242 | - 4 Log internal errors and check conditions to console | |
243 | - 5 panic on internal errors, log check conditions to console | |
244 | - 6 panic on both, internal errors and check conditions | |
245 | */ | |
246 | ||
247 | #ifndef DEBUG_LEVEL | |
248 | #define DEBUG_LEVEL 4 | |
249 | #endif | |
250 | ||
251 | #define INTERNAL_ERRMSG(x,y...) "E" __FILE__ "%d: " x, __LINE__, y | |
252 | #define INTERNAL_WRNMSG(x,y...) "W" __FILE__ "%d: " x, __LINE__, y | |
253 | #define INTERNAL_INFMSG(x,y...) "I" __FILE__ "%d: " x, __LINE__, y | |
254 | #define INTERNAL_DEBMSG(x,y...) "D" __FILE__ "%d: " x, __LINE__, y | |
255 | ||
256 | #if DEBUG_LEVEL > 0 | |
496da0d7 HC |
257 | #define PRINT_DEBUG(x...) printk(KERN_DEBUG PRINTK_HEADER x) |
258 | #define PRINT_INFO(x...) printk(KERN_INFO PRINTK_HEADER x) | |
259 | #define PRINT_WARN(x...) printk(KERN_WARNING PRINTK_HEADER x) | |
260 | #define PRINT_ERR(x...) printk(KERN_ERR PRINTK_HEADER x) | |
261 | #define PRINT_FATAL(x...) panic(PRINTK_HEADER x) | |
1da177e4 | 262 | #else |
496da0d7 HC |
263 | #define PRINT_DEBUG(x...) printk(KERN_DEBUG PRINTK_HEADER x) |
264 | #define PRINT_INFO(x...) printk(KERN_DEBUG PRINTK_HEADER x) | |
265 | #define PRINT_WARN(x...) printk(KERN_DEBUG PRINTK_HEADER x) | |
266 | #define PRINT_ERR(x...) printk(KERN_DEBUG PRINTK_HEADER x) | |
267 | #define PRINT_FATAL(x...) printk(KERN_DEBUG PRINTK_HEADER x) | |
268 | #endif /* DASD_DEBUG */ | |
269 | ||
270 | #endif /* DEBUG_H */ |