diff options
author | Peter Oberparleiter <oberpar@linux.ibm.com> | 2021-08-13 15:05:04 +0200 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2021-08-25 11:03:35 +0200 |
commit | d72541f945127b4873dace501406a1bc8cd8e1e9 (patch) | |
tree | 30147ce80aca7a485b637f4f9935204142b5bf63 /arch/s390/kernel/debug.c | |
parent | 9372a82892c2caa6bccab9a4081166fa769699f8 (diff) | |
download | lwn-d72541f945127b4873dace501406a1bc8cd8e1e9.tar.gz lwn-d72541f945127b4873dace501406a1bc8cd8e1e9.zip |
s390/debug: add early tracing support
Debug areas can currently only be used after s390dbf initialization
which occurs as a postcore_initcall. This is too late for tracing
earlier code such as that related to console_init().
This patch introduces a macro for defining a statically initialized
debug area that can be used to trace very early code. The macro is made
available for built-in code only because modules are never running
during early boot.
Example usage:
1. Define static debug area:
DEFINE_STATIC_DEBUG_INFO(my_debug, "my_debug", 4, 1, 16,
&debug_hex_ascii_view);
2. Add trace entry:
debug_event(&my_debug, 0, "DATA", 4);
Note: The debug area is automatically registered in debugfs during boot.
A driver must not call any of the debug_register()/_unregister()
functions on a static debug_info_t!
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'arch/s390/kernel/debug.c')
-rw-r--r-- | arch/s390/kernel/debug.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 05b765b8038e..da4d67736daa 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -692,6 +692,61 @@ debug_info_t *debug_register(const char *name, int pages_per_area, } EXPORT_SYMBOL(debug_register); +/** + * debug_register_static() - registers a static debug area + * + * @id: Handle for static debug area + * @pages_per_area: Number of pages per area + * @nr_areas: Number of debug areas + * + * Register debug_info_t defined using DEFINE_STATIC_DEBUG_INFO. + * + * Note: This function is called automatically via an initcall generated by + * DEFINE_STATIC_DEBUG_INFO. + */ +void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas) +{ + unsigned long flags; + debug_info_t *copy; + + if (!initialized) { + pr_err("Tried to register debug feature %s too early\n", + id->name); + return; + } + + copy = debug_info_alloc("", pages_per_area, nr_areas, id->buf_size, + id->level, ALL_AREAS); + if (!copy) { + pr_err("Registering debug feature %s failed\n", id->name); + + /* Clear pointers to prevent tracing into released initdata. */ + spin_lock_irqsave(&id->lock, flags); + id->areas = NULL; + id->active_pages = NULL; + id->active_entries = NULL; + spin_unlock_irqrestore(&id->lock, flags); + + return; + } + + /* Replace static trace area with dynamic copy. */ + spin_lock_irqsave(&id->lock, flags); + debug_events_append(copy, id); + debug_areas_swap(id, copy); + spin_unlock_irqrestore(&id->lock, flags); + + /* Clear pointers to initdata and discard copy. */ + copy->areas = NULL; + copy->active_pages = NULL; + copy->active_entries = NULL; + debug_info_free(copy); + + mutex_lock(&debug_mutex); + _debug_register(id); + mutex_unlock(&debug_mutex); +} + /* Remove debugfs entries and remove from internal list. */ static void _debug_unregister(debug_info_t *id) { |