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