From d72541f945127b4873dace501406a1bc8cd8e1e9 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Fri, 13 Aug 2021 15:05:04 +0200 Subject: 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 Signed-off-by: Heiko Carstens --- arch/s390/kernel/debug.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'arch/s390/kernel') 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) { -- cgit v1.2.3