^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * S/390 debug facility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright IBM Corp. 1999, 2020
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author(s): Michael Holzheu (holzheu@de.ibm.com),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Holger Smolinski (Holger.Smolinski@de.ibm.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Bugreports to: <Linux390@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #define KMSG_COMPONENT "s390dbf"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sysctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/minmax.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <asm/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DEBUG_PROLOG_ENTRY -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define ALL_AREAS 0 /* copy all debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define NO_AREAS 1 /* copy no debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* typedefs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) typedef struct file_private_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) loff_t offset; /* offset of last read in file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int act_area; /* number of last formated area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int act_page; /* act page in given area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int act_entry; /* last formated entry (offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* relative to beginning of last */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* formated page) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) size_t act_entry_offset; /* up to this offset we copied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* in last read the last formated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* entry to userland */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) char temp_buf[2048]; /* buffer for output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) debug_info_t *debug_info_org; /* original debug information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) debug_info_t *debug_info_snap; /* snapshot of debug information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct debug_view *view; /* used view of debug info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) } file_private_info_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) char *string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * This assumes that all args are converted into longs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * on L/390 this is the case for all types of parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * except of floats, and long long (32 bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) long args[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) } debug_sprintf_entry_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* internal function prototyes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int debug_init(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static ssize_t debug_output(struct file *file, char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) size_t user_len, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static ssize_t debug_input(struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) size_t user_len, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int debug_open(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static int debug_close(struct inode *inode, struct file *file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) static debug_info_t *debug_info_create(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int nr_areas, int buf_size, umode_t mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static void debug_info_get(debug_info_t *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void debug_info_put(debug_info_t *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static int debug_prolog_level_fn(debug_info_t *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct debug_view *view, char *out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static int debug_prolog_pages_fn(debug_info_t *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct debug_view *view, char *out_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) size_t user_buf_size, loff_t *offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) char *out_buf, const char *in_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) char *out_buf, debug_sprintf_entry_t *curr_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static void debug_events_append(debug_info_t *dest, debug_info_t *src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) struct debug_view debug_hex_ascii_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) "hex_ascii",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) &debug_dflt_header_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) &debug_hex_ascii_format_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) EXPORT_SYMBOL(debug_hex_ascii_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static struct debug_view debug_level_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) "level",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) &debug_prolog_level_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) &debug_input_level_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static struct debug_view debug_pages_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) "pages",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) &debug_prolog_pages_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) &debug_input_pages_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct debug_view debug_flush_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "flush",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) &debug_input_flush_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct debug_view debug_sprintf_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) "sprintf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) &debug_dflt_header_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) (debug_format_proc_t *)&debug_sprintf_format_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) EXPORT_SYMBOL(debug_sprintf_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /* used by dump analysis tools to determine version of debug feature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* static globals */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static debug_info_t *debug_area_first;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static debug_info_t *debug_area_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static DEFINE_MUTEX(debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static int initialized;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int debug_critical;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static const struct file_operations debug_file_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .read = debug_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .write = debug_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .open = debug_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .release = debug_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) static struct dentry *debug_debugfs_root_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * debug_areas_alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * - Debug areas are implemented as a threedimensonal array:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * areas[areanumber][pagenumber][pageoffset]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static debug_entry_t ***debug_areas_alloc(int pages_per_area, int nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) debug_entry_t ***areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) areas = kmalloc_array(nr_areas, sizeof(debug_entry_t **), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) goto fail_malloc_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; i < nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* GFP_NOWARN to avoid user triggerable WARN, we handle fails */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) areas[i] = kmalloc_array(pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) sizeof(debug_entry_t *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) GFP_KERNEL | __GFP_NOWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!areas[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto fail_malloc_areas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) for (j = 0; j < pages_per_area; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) areas[i][j] = kzalloc(PAGE_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!areas[i][j]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) for (j--; j >= 0 ; j--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) kfree(areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) kfree(areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto fail_malloc_areas2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) fail_malloc_areas2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) for (i--; i >= 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) for (j = 0; j < pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) kfree(areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) kfree(areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) kfree(areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) fail_malloc_areas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * debug_info_alloc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * - alloc new debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static debug_info_t *debug_info_alloc(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int nr_areas, int buf_size, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) /* alloc everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) rc = kmalloc(sizeof(debug_info_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto fail_malloc_rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) rc->active_entries = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!rc->active_entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) goto fail_malloc_active_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) rc->active_pages = kcalloc(nr_areas, sizeof(int), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if (!rc->active_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) goto fail_malloc_active_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if ((mode == ALL_AREAS) && (pages_per_area != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!rc->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) goto fail_malloc_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) rc->areas = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /* initialize members */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) spin_lock_init(&rc->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) rc->pages_per_area = pages_per_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) rc->nr_areas = nr_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) rc->active_area = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) rc->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) rc->buf_size = buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) rc->entry_size = sizeof(debug_entry_t) + buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) strlcpy(rc->name, name, sizeof(rc->name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) memset(rc->debugfs_entries, 0, DEBUG_MAX_VIEWS * sizeof(struct dentry *));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) refcount_set(&(rc->ref_count), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) fail_malloc_areas:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) kfree(rc->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fail_malloc_active_pages:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) kfree(rc->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) fail_malloc_active_entries:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) kfree(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) fail_malloc_rc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * debug_areas_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * - free all debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static void debug_areas_free(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!db_info->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) for (i = 0; i < db_info->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) for (j = 0; j < db_info->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) kfree(db_info->areas[i][j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) kfree(db_info->areas[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) kfree(db_info->areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) db_info->areas = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * debug_info_free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * - free memory debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static void debug_info_free(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) debug_areas_free(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) kfree(db_info->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) kfree(db_info->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) kfree(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * debug_info_create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * - create new debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) static debug_info_t *debug_info_create(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) int nr_areas, int buf_size, umode_t mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) DEBUG_DEFAULT_LEVEL, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) rc->mode = mode & ~S_IFMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) refcount_set(&rc->ref_count, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * debug_info_copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * - copy debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static debug_info_t *debug_info_copy(debug_info_t *in, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) debug_info_t *rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* get a consistent copy of the debug areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) rc = debug_info_alloc(in->name, in->pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) in->nr_areas, in->buf_size, in->level, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) spin_lock_irqsave(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /* has something changed in the meantime ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if ((rc->pages_per_area == in->pages_per_area) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) (rc->nr_areas == in->nr_areas)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) spin_unlock_irqrestore(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) debug_info_free(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (mode == NO_AREAS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) for (i = 0; i < in->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) for (j = 0; j < in->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) memcpy(rc->areas[i][j], in->areas[i][j], PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) spin_unlock_irqrestore(&in->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) * debug_info_get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * - increments reference count for debug-info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static void debug_info_get(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) if (db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) refcount_inc(&db_info->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * debug_info_put:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * - decreases reference count for debug-info and frees it if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) static void debug_info_put(debug_info_t *db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (!db_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) if (refcount_dec_and_test(&db_info->ref_count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) debug_info_free(db_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * debug_format_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * - format one debug entry and return size of formated data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) static int debug_format_entry(file_private_info_t *p_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) debug_info_t *id_snap = p_info->debug_info_snap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct debug_view *view = p_info->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) debug_entry_t *act_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) size_t len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* print prolog */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (view->prolog_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) len += view->prolog_proc(id_snap, view, p_info->temp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (!id_snap->areas) /* this is true, if we have a prolog only view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) goto out; /* or if 'pages_per_area' is 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) act_entry = (debug_entry_t *) ((char *)id_snap->areas[p_info->act_area]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) [p_info->act_page] + p_info->act_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (act_entry->clock == 0LL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) goto out; /* empty entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (view->header_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) len += view->header_proc(id_snap, view, p_info->act_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) act_entry, p_info->temp_buf + len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (view->format_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) len += view->format_proc(id_snap, view, p_info->temp_buf + len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) DEBUG_DATA(act_entry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * debug_next_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * - goto next entry in p_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static inline int debug_next_entry(file_private_info_t *p_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) debug_info_t *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) id = p_info->debug_info_snap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) p_info->act_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) p_info->act_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) p_info->act_entry += id->entry_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* switch to next page, if we reached the end of the page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (p_info->act_entry > (PAGE_SIZE - id->entry_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* next page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) p_info->act_entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) p_info->act_page += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if ((p_info->act_page % id->pages_per_area) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* next area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) p_info->act_area++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) p_info->act_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (p_info->act_area >= id->nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * debug_output:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * - called for user read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * - copies formated debug entries to the user buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static ssize_t debug_output(struct file *file, /* file descriptor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) char __user *user_buf, /* user buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) size_t len, /* length of buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) loff_t *offset) /* offset in the file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) size_t count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) size_t entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) p_info = (file_private_info_t *) file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (*offset != p_info->offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (p_info->act_area >= p_info->debug_info_snap->nr_areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) entry_offset = p_info->act_entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) while (count < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) int formatted_line_residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) int formatted_line_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int user_buf_residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) size_t copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) formatted_line_size = debug_format_entry(p_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) formatted_line_residue = formatted_line_size - entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) user_buf_residue = len-count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) copy_size = min(user_buf_residue, formatted_line_residue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (copy_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (copy_to_user(user_buf + count, p_info->temp_buf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) + entry_offset, copy_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) count += copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) entry_offset += copy_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (copy_size == formatted_line_residue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) entry_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (debug_next_entry(p_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) p_info->offset = *offset + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) p_info->act_entry_offset = entry_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) *offset = p_info->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) * debug_input:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * - called for user write()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) * - calls input function of view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) static ssize_t debug_input(struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) size_t length, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) p_info = ((file_private_info_t *) file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (p_info->view->input_proc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) rc = p_info->view->input_proc(p_info->debug_info_org,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) p_info->view, file, user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) length, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) rc = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) return rc; /* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * debug_open:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) * - called for user open()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * - copies formated output to private_data area of the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) static int debug_open(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) debug_info_t *debug_info, *debug_info_snapshot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) debug_info = file_inode(file)->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) /* find debug view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (!debug_info->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) else if (debug_info->debugfs_entries[i] == file->f_path.dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto found; /* found view ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) /* no entry found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /* Make snapshot of current debug areas to get it consistent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) /* To copy all the areas is only needed, if we have a view which */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* formats the debug areas. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) if (!debug_info->views[i]->format_proc && !debug_info->views[i]->header_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (!debug_info_snapshot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) p_info = kmalloc(sizeof(file_private_info_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!p_info) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) debug_info_free(debug_info_snapshot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) rc = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) p_info->offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) p_info->debug_info_snap = debug_info_snapshot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) p_info->debug_info_org = debug_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) p_info->view = debug_info->views[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) p_info->act_area = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) p_info->act_page = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) p_info->act_entry = DEBUG_PROLOG_ENTRY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) p_info->act_entry_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) file->private_data = p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) debug_info_get(debug_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) nonseekable_open(inode, file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * debug_close:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * - called for user close()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * - deletes private_data area of the file handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int debug_close(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) file_private_info_t *p_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) p_info = (file_private_info_t *) file->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) if (p_info->debug_info_snap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) debug_info_free(p_info->debug_info_snap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) debug_info_put(p_info->debug_info_org);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) kfree(file->private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return 0; /* success */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /* Create debugfs entries and add to internal list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) static void _debug_register(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* create root directory */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) id->debugfs_root_entry = debugfs_create_dir(id->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) debug_debugfs_root_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) /* append new element to linked list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (!debug_area_first) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* first element in list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) debug_area_first = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) id->prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* append element to end of list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) debug_area_last->next = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) id->prev = debug_area_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) debug_area_last = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) id->next = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) debug_register_view(id, &debug_level_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) debug_register_view(id, &debug_flush_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) debug_register_view(id, &debug_pages_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * debug_register_mode() - creates and initializes debug area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) * @name: Name of debug log (e.g. used for debugfs entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) * @pages_per_area: Number of pages, which will be allocated per area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * @nr_areas: Number of debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * @buf_size: Size of data area in each debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) * @mode: File mode for debugfs files. E.g. S_IRWXUGO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * @uid: User ID for debugfs files. Currently only 0 is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * @gid: Group ID for debugfs files. Currently only 0 is supported.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * - Handle for generated debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * - %NULL if register failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * Allocates memory for a debug log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * Must not be called within an interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) debug_info_t *debug_register_mode(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) int nr_areas, int buf_size, umode_t mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) uid_t uid, gid_t gid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) debug_info_t *rc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) /* Since debugfs currently does not support uid/gid other than root, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) /* we do not allow gid/uid != 0 until we get support for that. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if ((uid != 0) || (gid != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) pr_warn("Root becomes the owner of all s390dbf files in sysfs\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) BUG_ON(!initialized);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) /* create new debug_info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) _debug_register(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) pr_err("Registering debug feature %s failed\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) EXPORT_SYMBOL(debug_register_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * debug_register() - creates and initializes debug area with default file mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * @name: Name of debug log (e.g. used for debugfs entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * @pages_per_area: Number of pages, which will be allocated per area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * @nr_areas: Number of debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * @buf_size: Size of data area in each debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * - Handle for generated debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * - %NULL if register failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * Allocates memory for a debug log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * The debugfs file mode access permissions are read and write for user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * Must not be called within an interrupt handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) debug_info_t *debug_register(const char *name, int pages_per_area,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) int nr_areas, int buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) S_IRUSR | S_IWUSR, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) EXPORT_SYMBOL(debug_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /* Remove debugfs entries and remove from internal list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) static void _debug_unregister(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (!id->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) debugfs_remove(id->debugfs_entries[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) debugfs_remove(id->debugfs_root_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (id == debug_area_first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) debug_area_first = id->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (id == debug_area_last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) debug_area_last = id->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (id->prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) id->prev->next = id->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (id->next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) id->next->prev = id->prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * debug_unregister() - give back debug area.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * @id: handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) * none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) void debug_unregister(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) _debug_unregister(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) debug_info_put(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) EXPORT_SYMBOL(debug_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) * debug_set_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * - set area size (number of pages) and number of areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) static int debug_set_size(debug_info_t *id, int nr_areas, int pages_per_area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) debug_info_t *new_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (!id || (nr_areas <= 0) || (pages_per_area < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) new_id = debug_info_alloc("", pages_per_area, nr_areas, id->buf_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) id->level, ALL_AREAS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (!new_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) pr_info("Allocating memory for %i pages failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) debug_events_append(new_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) debug_areas_swap(new_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) debug_info_free(new_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) pr_info("%s: set new size (%i pages)\n", id->name, pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * debug_set_level() - Sets new actual debug level if new_level is valid.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * @id: handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * @new_level: new debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) * none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) void debug_set_level(debug_info_t *id, int new_level)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (new_level == DEBUG_OFF_LEVEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) id->level = DEBUG_OFF_LEVEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) pr_info("%s: switched off\n", id->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) pr_info("%s: level %i is out of range (%i - %i)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) id->name, new_level, 0, DEBUG_MAX_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) id->level = new_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) EXPORT_SYMBOL(debug_set_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * proceed_active_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * - set active entry to next in the ring buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) static inline void proceed_active_entry(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) if ((id->active_entries[id->active_area] += id->entry_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) > (PAGE_SIZE - id->entry_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) id->active_entries[id->active_area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) id->active_pages[id->active_area] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) (id->active_pages[id->active_area] + 1) %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) id->pages_per_area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * proceed_active_area:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * - set active area to next in the ring buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) static inline void proceed_active_area(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) id->active_area++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) id->active_area = id->active_area % id->nr_areas;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * get_active_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static inline debug_entry_t *get_active_entry(debug_info_t *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) return (debug_entry_t *) (((char *) id->areas[id->active_area]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) [id->active_pages[id->active_area]]) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) id->active_entries[id->active_area]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /* Swap debug areas of a and b. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static void debug_areas_swap(debug_info_t *a, debug_info_t *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) swap(a->nr_areas, b->nr_areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) swap(a->pages_per_area, b->pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) swap(a->areas, b->areas);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) swap(a->active_area, b->active_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) swap(a->active_pages, b->active_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) swap(a->active_entries, b->active_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /* Append all debug events in active area from source to destination log. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static void debug_events_append(debug_info_t *dest, debug_info_t *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) debug_entry_t *from, *to, *last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (!src->areas || !dest->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* Loop over all entries in src, starting with oldest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) from = get_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) last = from;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (from->clock != 0LL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) to = get_active_entry(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) memset(to, 0, dest->entry_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) memcpy(to, from, min(src->entry_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) dest->entry_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) proceed_active_entry(dest);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) proceed_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) from = get_active_entry(src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) } while (from != last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * debug_finish_entry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * - set timestamp, caller address, cpu number etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static inline void debug_finish_entry(debug_info_t *id, debug_entry_t *active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) int level, int exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) unsigned char clk[STORE_CLOCK_EXT_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) unsigned long timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) get_tod_clock_ext(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) timestamp = *(unsigned long *) &clk[0] >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) timestamp -= TOD_UNIX_EPOCH >> 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) active->clock = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) active->cpu = smp_processor_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) active->caller = __builtin_return_address(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) active->exception = exception;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) active->level = level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) proceed_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) proceed_active_area(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) static int debug_stoppable = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static int debug_active = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) #define CTL_S390DBF_STOPPABLE 5678
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) #define CTL_S390DBF_ACTIVE 5679
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * proc handler for the running debug_active sysctl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * always allow read, allow write only if debug_stoppable is set or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * if debug_active is already off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int s390dbf_procactive(struct ctl_table *table, int write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) void *buffer, size_t *lenp, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (!write || debug_stoppable || !debug_active)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return proc_dointvec(table, write, buffer, lenp, ppos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static struct ctl_table s390dbf_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .procname = "debug_stoppable",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .data = &debug_stoppable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .maxlen = sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .mode = S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .proc_handler = proc_dointvec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .procname = "debug_active",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .data = &debug_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .maxlen = sizeof(int),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .mode = S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .proc_handler = s390dbf_procactive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) static struct ctl_table s390dbf_dir_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) .procname = "s390dbf",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) .maxlen = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) .mode = S_IRUGO | S_IXUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) .child = s390dbf_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static struct ctl_table_header *s390dbf_sysctl_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * debug_stop_all() - stops the debug feature if stopping is allowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) * - none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * Currently used in case of a kernel oops.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) void debug_stop_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (debug_stoppable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) debug_active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) EXPORT_SYMBOL(debug_stop_all);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * debug_set_critical() - event/exception functions try lock instead of spin.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * - none
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) * Currently used in case of stopping all CPUs but the current one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) * Once in this state, functions to write a debug entry for an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) * event or exception no longer spin on the debug area lock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * but only try to get it and fail if they do not get the lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) void debug_set_critical(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) debug_critical = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * debug_event_common:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * - write debug entry with given size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) debug_entry_t *debug_event_common(debug_info_t *id, int level, const void *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) if (len < id->buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) memset((DEBUG_DATA(active)) + len, 0, id->buf_size - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) debug_finish_entry(id, active, level, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) len -= id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) buf += id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) } while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) EXPORT_SYMBOL(debug_event_common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * debug_exception_common:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * - write debug entry with given size and switch to next debug area
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) debug_entry_t *debug_exception_common(debug_info_t *id, int level,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) const void *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) if (len < id->buf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) memset((DEBUG_DATA(active)) + len, 0, id->buf_size - len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) debug_finish_entry(id, active, level, len <= id->buf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) len -= id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) buf += id->buf_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) } while (len > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) EXPORT_SYMBOL(debug_exception_common);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) * counts arguments in format string for sprintf view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) static inline int debug_count_numargs(char *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) int numargs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) while (*string) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (*string++ == '%')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) numargs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return numargs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * debug_sprintf_event:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) debug_entry_t *__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) debug_sprintf_entry_t *curr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) int numargs, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) numargs = debug_count_numargs(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) curr_event = (debug_sprintf_entry_t *) DEBUG_DATA(active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) va_start(ap, string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) curr_event->string = string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) for (idx = 0; idx < min(numargs, (int)(id->buf_size / sizeof(long)) - 1); idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) curr_event->args[idx] = va_arg(ap, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) debug_finish_entry(id, active, level, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) EXPORT_SYMBOL(__debug_sprintf_event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) * debug_sprintf_exception:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) debug_entry_t *__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) debug_sprintf_entry_t *curr_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) debug_entry_t *active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) int numargs, idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (!debug_active || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) numargs = debug_count_numargs(string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) if (debug_critical) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (!spin_trylock_irqsave(&id->lock, flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) active = get_active_entry(id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) curr_event = (debug_sprintf_entry_t *)DEBUG_DATA(active);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) va_start(ap, string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) curr_event->string = string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) for (idx = 0; idx < min(numargs, (int)(id->buf_size / sizeof(long)) - 1); idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) curr_event->args[idx] = va_arg(ap, long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) debug_finish_entry(id, active, level, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) return active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) EXPORT_SYMBOL(__debug_sprintf_exception);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * debug_register_view() - registers new debug view and creates debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * dir entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * @id: handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * @view: pointer to debug view struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) * - 0 : ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) * - < 0: Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) int debug_register_view(debug_info_t *id, struct debug_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) struct dentry *pde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) umode_t mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) mode = (id->mode | S_IFREG) & ~S_IXUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) if (!(view->prolog_proc || view->format_proc || view->header_proc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) mode &= ~(S_IRUSR | S_IRGRP | S_IROTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (!view->input_proc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) id, &debug_file_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) if (!id->views[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) if (i == DEBUG_MAX_VIEWS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) pr_err("Registering view %s/%s would exceed the maximum "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) "number of views %i\n", id->name, view->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) id->views[i] = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) id->debugfs_entries[i] = pde;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) debugfs_remove(pde);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) EXPORT_SYMBOL(debug_register_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) * debug_unregister_view() - unregisters debug view and removes debugfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) * dir entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * @id: handle for debug log
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * @view: pointer to debug view struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) * - 0 : ok
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) * - < 0: Error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) int debug_unregister_view(debug_info_t *id, struct debug_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct dentry *dentry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) if (id->views[i] == view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (i == DEBUG_MAX_VIEWS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) rc = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) dentry = id->debugfs_entries[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) id->views[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) id->debugfs_entries[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) debugfs_remove(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) EXPORT_SYMBOL(debug_unregister_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) static inline char *debug_get_user_string(const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) size_t user_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) buffer = kmalloc(user_len + 1, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) if (copy_from_user(buffer, user_buf, user_len) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return ERR_PTR(-EFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) /* got the string, now strip linefeed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (buffer[user_len - 1] == '\n')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) buffer[user_len - 1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) buffer[user_len] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) return buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) static inline int debug_get_uint(char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) buf = skip_spaces(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) rc = simple_strtoul(buf, &buf, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (*buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) * functions for debug-views
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) ***********************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * prints out actual debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) static int debug_prolog_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) return sprintf(out_buf, "%i\n", id->pages_per_area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) * reads new size (number of pages per debug area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) int rc, new_pages;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) str = debug_get_user_string(user_buf, user_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (IS_ERR(str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) rc = PTR_ERR(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) new_pages = debug_get_uint(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (new_pages < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) rc = debug_set_size(id, id->nr_areas, new_pages);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) if (rc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) free_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) kfree(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) *offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return rc; /* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * prints out actual debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) static int debug_prolog_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (id->level == DEBUG_OFF_LEVEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) rc = sprintf(out_buf, "-\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) rc = sprintf(out_buf, "%i\n", id->level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) * reads new debug level
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) int rc, new_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) str = debug_get_user_string(user_buf, user_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) if (IS_ERR(str)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) rc = PTR_ERR(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (str[0] == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) debug_set_level(id, DEBUG_OFF_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) goto free_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) new_level = debug_get_uint(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (new_level < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) pr_warn("%s is not a valid level for a debug feature\n", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) debug_set_level(id, new_level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) free_str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) kfree(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) *offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) return rc; /* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) * flushes debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) static void debug_flush(debug_info_t *id, int area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) if (!id || !id->areas)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) spin_lock_irqsave(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) if (area == DEBUG_FLUSH_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) id->active_area = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) memset(id->active_entries, 0, id->nr_areas * sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) for (i = 0; i < id->nr_areas; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) id->active_pages[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) for (j = 0; j < id->pages_per_area; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) memset(id->areas[i][j], 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) } else if (area >= 0 && area < id->nr_areas) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) id->active_entries[area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) id->active_pages[area] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) for (i = 0; i < id->pages_per_area; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) memset(id->areas[area][i], 0, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) spin_unlock_irqrestore(&id->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * view function: flushes debug areas
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct file *file, const char __user *user_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) size_t user_len, loff_t *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) char input_buf[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) int rc = user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (user_len > 0x10000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) user_len = 0x10000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (*offset != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) rc = -EPIPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (copy_from_user(input_buf, user_buf, 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) rc = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) if (input_buf[0] == '-') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) debug_flush(id, DEBUG_FLUSH_ALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) if (isdigit(input_buf[0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) int area = ((int) input_buf[0] - (int) '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) debug_flush(id, area);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) pr_info("Flushing debug data failed because %c is not a valid "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) "area\n", input_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) *offset += user_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return rc; /* number of input characters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * prints debug data in hex/ascii format
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) char *out_buf, const char *in_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) int i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) for (i = 0; i < id->buf_size; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) rc += sprintf(out_buf + rc, "%02x ", ((unsigned char *) in_buf)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) rc += sprintf(out_buf + rc, "| ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) for (i = 0; i < id->buf_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) unsigned char c = in_buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) if (isascii(c) && isprint(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) rc += sprintf(out_buf + rc, "%c", c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) rc += sprintf(out_buf + rc, ".");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) rc += sprintf(out_buf + rc, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * prints header for debug entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) int area, debug_entry_t *entry, char *out_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) unsigned long sec, usec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) unsigned long caller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) unsigned int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) char *except_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) level = entry->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) sec = entry->clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) usec = do_div(sec, USEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (entry->exception)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) except_str = "*";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) except_str = "-";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) caller = (unsigned long) entry->caller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %04u %pK ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) area, sec, usec, level, except_str,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) entry->cpu, (void *)caller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) EXPORT_SYMBOL(debug_dflt_header_fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) * prints debug data sprintf-formated:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) * debug_sprinf_event/exception calls must be used together with this view
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) #define DEBUG_SPRINTF_MAX_ARGS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) char *out_buf, debug_sprintf_entry_t *curr_event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) int num_longs, num_used_args = 0, i, rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) int index[DEBUG_SPRINTF_MAX_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) /* count of longs fit into one entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) num_longs = id->buf_size / sizeof(long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) if (num_longs < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) goto out; /* bufsize of entry too small */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (num_longs == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) /* no args, we use only the string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) strcpy(out_buf, curr_event->string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) rc = strlen(curr_event->string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) /* number of arguments used for sprintf (without the format string) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) num_used_args = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) memset(index, 0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) for (i = 0; i < num_used_args; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) index[i] = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) curr_event->args[index[1]], curr_event->args[index[2]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) curr_event->args[index[3]], curr_event->args[index[4]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) curr_event->args[index[5]], curr_event->args[index[6]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) curr_event->args[index[7]], curr_event->args[index[8]],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) curr_event->args[index[9]]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * debug_init:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * - is called exactly once to initialize the debug feature
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static int __init debug_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) mutex_lock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) initialized = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) mutex_unlock(&debug_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) postcore_initcall(debug_init);