Dynamic Debug providing early boot debug messages via boot parameter
Subsystems (3)
cover Dynamic Debug providing early boot debug messages via boot parameter
Sorry about the first post, missing two patches, please ignore...
this patch is against 2.6.35-rc5. Not sure whether Jason's latest fix is in there already and whether it conflicts with this series, but it should patch.
Please tell me if I should (have to) re-diff and against which branch I should do that.
The patches got boot tested via ddebug_query="file ec.c +p" which worked out fine.
Would be great to see these in the next kernel cycle (2.6.36).
Thanks,
Thomas
Signature · 1 line
������$ز|��I�\��bI'z�楖��'���'%&gsu�3��%`*���&(����}i�.���I�*i>?��,���0�m����6�77�0
PATCH 1/3 Dynamic Debug: Split out query string parsing/setup from proc_write
The parsing and applying of dynamic debug strings is not only useful for /sys/../dynamic_debug/control write access, but can also be used for boot parameter parsing.
The boot parameter is introduced in a follow up patch.
--- lib/dynamic_debug.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-)
lib/dynamic_debug.c +25 -15
@@ -429,6 +429,27 @@ static int ddebug_parse_flags(const charreturn 0 ; } +static int ddebug_exec_query (char *query_string) +{ +unsigned int flags =0 , mask =0 ; +struct ddebug_query query; +#define MAXWORDS 9 +int nwords; +char *words[MAXWORDS ]; + + nwords =ddebug_tokenize (query_string, words,MAXWORDS ); +if (nwords <=0 ) +return -EINVAL ; +if (ddebug_parse_query (words, nwords-1 , &query)) +return -EINVAL ; +if (ddebug_parse_flags (words[nwords-1 ], &flags, &mask)) +return -EINVAL ; + +/* actually go and implement the change */ +ddebug_change (&query, flags, mask); +return 0 ; +} +/* * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the * command text from userspace, parses and executes it.
@@ -436,12 +457,8 @@ static int ddebug_parse_flags(const charstatic ssize_t ddebug_proc_write (struct file *file,const char __user *ubuf,size_t len,loff_t *offp) { -unsigned int flags =0 , mask =0 ; -struct ddebug_query query; -#define MAXWORDS 9 -int nwords; -char *words[MAXWORDS ];char tmpbuf[256 ]; +int ret;if (len ==0 )return 0 ;
@@ -455,16 +472,9 @@ static ssize_t ddebug_proc_write(structprintk (KERN_INFO "%s: read %d bytes from userspace\n" , __func__, (int )len); - nwords =ddebug_tokenize (tmpbuf, words,MAXWORDS ); -if (nwords <=0 ) -return -EINVAL ; -if (ddebug_parse_query (words, nwords-1 , &query)) -return -EINVAL ; -if (ddebug_parse_flags (words[nwords-1 ], &flags, &mask)) -return -EINVAL ; - -/* actually go and implement the change */ -ddebug_change (&query, flags, mask); + ret =ddebug_exec_query (tmpbuf); +if (ret) +return ret; *offp += len;return len;
PATCH 2/3 Dynamic Debug: Introduce ddebug_query= boot parameter
In reply to [email protected]Dynamic debug lacks the ability to enable debug messages at boot time. One could patch initramfs or service startup scripts to write to /sys/../dynamic_debug/control, but this sucks.
This patch makes it possible to pass a query in the same format one can write to /sys/../dynamic_debug/control via boot param.
When dynamic debug gets initialized, this query will automatically be applied.
--- Documentation/dynamic-debug-howto.txt | 22 +++++++++++++++++++++- Documentation/kernel-parameters.txt | 7 ++++++- lib/dynamic_debug.c | 25 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 2 deletions(-)
lib/dynamic_debug.c +25 -0
@@ -450,6 +450,19 @@ static int ddebug_exec_query(char *queryreturn 0 ; } +static __initdata char ddebug_setup_string[1024 ]; +static __init int ddebug_setup_query (char *str) +{ +if (strlen (str) >=1024 ) { +pr_warning ("ddebug boot param string too large\n" ); +return 0 ; + } +strcpy (ddebug_setup_string, str); +return 1 ; +} + +__setup ("ddebug_query=" , ddebug_setup_query); +/* * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the * command text from userspace, parses and executes it.
@@ -769,6 +782,18 @@ static int __init dynamic_debug_init(voi } ret =ddebug_add_module (iter_start, n, modname); } + +/* ddebug_query boot param got passed -> set it up */ +if (ddebug_setup_string[0 ] !='\0' ) { + ret =ddebug_exec_query (ddebug_setup_string); +if (ret) +pr_warning ("Invalid ddebug boot param %s" , + ddebug_setup_string); +else +pr_info ("ddebug initialized with string %s" , + ddebug_setup_string); + } + out_free:if (ret) {ddebug_remove_all_tables ();
Documentation/dynamic-debug-howto.txt +21 -1
@@ -24,7 +24,7 @@ Dynamic debug has even more useful featu read to display the complete list of known debug statements, to help guide you Controlling dynamic debug Behaviour -=============================== +=================================== The behaviour of pr_debug()/dev_debug()s are controlled via writing to a control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
@@ -212,6 +212,26 @@ Note the regexp ^[-+=][scp]+$ matches a Note also that there is no convenient syntax to remove all the flags at once, you need to use "-psc". + +Debug messages during boot process +================================== + +To be able to activate debug messages during the boot process, +even before userspace and debugfs exists, use the boot parameter: +ddebug_query="QUERY" + +QUERY follows the syntax described above, but must not exceed 1023 +characters. The enablement of debug messages is done as an arch_initcall. +Thus you can enable debug messages in all code processed after this +arch_initcall via this boot parameter. +On an x86 system for example ACPI enablement is a subsys_initcall and +ddebug_query="file ec.c +p" +will show early Embedded Controller transactions during ACPI setup if +your machine (typically a laptop) has an Embedded Controller. +PCI (or other devices) initialization also is a hot candidate for using +this boot parameter for debugging purposes. + + Examples ========
Documentation/kernel-parameters.txt +6 -1
@@ -43,10 +43,11 @@ parameter is applicable: AVR32 AVR32 architecture is enabled. AX25 Appropriate AX.25 support is enabled. BLACKFIN Blackfin architecture is enabled. - DRM Direct Rendering Management support is enabled. EDD BIOS Enhanced Disk Drive Services (EDD) is enabled EFI EFI Partitioning (GPT) is enabled EIDE EIDE/ATAPI support is enabled. + DRM Direct Rendering Management support is enabled. + DYNAMIC_DEBUG Build in debug messages and enable them at runtime FB The frame buffer device is enabled. GCOV GCOV profiling is enabled. HW Appropriate hardware is enabled.
@@ -601,6 +602,10 @@ and is between 256 and 4096 characters. Format: <port#>,<type> See also Documentation/input/joystick-parport.txt + ddebug_query= [KNL,DYNAMIC_DEBUG] Enable debug messages at early boot + time. See Documentation/dynamic-debug-howto.txt for + details. + debug [KNL] Enable kernel debugging (events log level). debug_locks_verbose=
PATCH 3/3 Dynamic Debug: Initialize dynamic debug earlier via arch_initcall
In reply to [email protected]Having the ddebug_query= boot parameter it makes sense to set up dynamic debug as soon as possible.
I expect sysfs files cannot be set up via an arch_initcall, because this one is even before fs_initcall. Therefore I splitted the dynamic_debug_init function into an early one and a later one providing /sys/../dynamic_debug/control file.
Possibly dynamic_debug can be initialized even earlier, not sure whether this still makes sense then. I picked up arch_initcall as it covers quite a lot already.
Dynamic debug seem to not need memory (kmalloc) set up yet.
If it is possible to move initialization even before __setup boot parameter processing, the temporary variable to copy away the boot paramter and later use it in dynamic_debug_init() is not needed anymore.
This has been tested with ddebug_query="file ec.c +p"
and I could retrieve pr_debug() messages early at boot during ACPI setup:
ACPI: EC: Look up EC in DSDT
ACPI: EC: ---> status = 0x08
ACPI: EC: transaction start
ACPI: EC: <--- command = 0x80
ACPI: EC: ~~~> interrupt
ACPI: EC: ---> status = 0x08
ACPI: EC: <--- data = 0xa4
...
ACPI: Interpreter enabled
ACPI: (supports S0 S3 S4 S5)
ACPI: Using IOAPIC for interrupt routing
ACPI: EC: ---> status = 0x00
ACPI: EC: transaction start
ACPI: EC: <--- command = 0x80
--- lib/dynamic_debug.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
lib/dynamic_debug.c +23 -10
@@ -748,13 +748,14 @@ static void ddebug_remove_all_tables(voimutex_unlock (&ddebug_lock); } -static int __init dynamic_debug_init (void ) +static __initdata int ddebug_init_success; + +static int __init dynamic_debug_init_debugfs (void ) {struct dentry *dir, *file; -struct _ddebug *iter, *iter_start; -const char *modname =NULL ; -int ret =0 ; -int n =0 ; + +if (!ddebug_init_success) +return -ENODEV ; dir =debugfs_create_dir ("dynamic_debug" ,NULL );if (!dir)
@@ -765,6 +766,16 @@ static int __init dynamic_debug_init(voidebugfs_remove (dir);return -ENOMEM ; } +return 0 ; +} + +static int __init dynamic_debug_init (void ) +{ +struct _ddebug *iter, *iter_start; +const char *modname =NULL ; +int ret =0 ; +int n =0 ; +if (__start___verbose != __stop___verbose) { iter = __start___verbose; modname = iter->modname;
@@ -795,11 +806,13 @@ static int __init dynamic_debug_init(voi } out_free: -if (ret) { +if (ret)ddebug_remove_all_tables (); -debugfs_remove (dir); -debugfs_remove (file); - } +else + ddebug_init_success =1 ;return 0 ; } -module_init (dynamic_debug_init); +/* Allow early initialization for boot messages via boot param */ +arch_initcall (dynamic_debug_init); +/* Debugfs setup must be done later */ +module_init (dynamic_debug_init_debugfs);