summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorPeter Oberparleiter <oberpar@linux.ibm.com>2021-08-13 15:05:04 +0200
committerHeiko Carstens <hca@linux.ibm.com>2021-08-25 11:03:35 +0200
commitd72541f945127b4873dace501406a1bc8cd8e1e9 (patch)
tree30147ce80aca7a485b637f4f9935204142b5bf63 /arch/s390/kernel
parent9372a82892c2caa6bccab9a4081166fa769699f8 (diff)
downloadlinux-d72541f945127b4873dace501406a1bc8cd8e1e9.tar.bz2
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')
-rw-r--r--arch/s390/kernel/debug.c55
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)
{