diff mbox series

[3/4] xen: print lock profile info in panic()

Message ID 20190807143119.8360-4-jgross@suse.com (mailing list archive)
State Superseded
Headers show
Series enhance lock debugging | expand

Commit Message

Jürgen Groß Aug. 7, 2019, 2:31 p.m. UTC
Print the lock profile data when the system crashes and add some more
information for each lock data (lock address, cpu holding the lock).

This is especially beneficial for watchdog triggered crashes in case
of deadlocks.

In order to have the cpu holding the lock available let the
LOCK_PROFILE config option select SPINLOCK_DEBUG.

As printing the lock profile data will make use of locking, too, we
need to disable spinlock debugging before calling
spinlock_profile_printall() from panic().

While at it remove a superfluous #ifdef CONFIG_LOCK_PROFILE.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 xen/Kconfig.debug          |  1 +
 xen/common/spinlock.c      | 11 +++++++----
 xen/drivers/char/console.c |  4 +++-
 xen/include/xen/spinlock.h |  1 +
 4 files changed, 12 insertions(+), 5 deletions(-)

Comments

Jan Beulich Aug. 8, 2019, 7:09 a.m. UTC | #1
On 07.08.2019 16:31, Juergen Gross wrote:
> --- a/xen/Kconfig.debug
> +++ b/xen/Kconfig.debug
> @@ -53,6 +53,7 @@ config SPINLOCK_DEBUG
>   
>   config LOCK_PROFILE
>   	bool "Lock Profiling"
> +	select SPINLOCK_DEBUG
>   	---help---
>   	  Lock profiling allows you to see how often locks are taken and blocked.
>   	  You can use serial console to print (and reset) using 'l' and 'L'

In which case, for sensible user experience, the selected
option should come after this one. The way it is now afaict
there'll be a prompt for SPINLOCK_DEBUG, the user may say
"no", just to find that because of saying "yes" here it'll
be turned on anyway. Whereas with switched ordering there'll
be no prompt for the debug option at all (again afaict) if
the profiling option was set to "yes".

Jan
Jürgen Groß Aug. 8, 2019, 8:26 a.m. UTC | #2
On 08.08.19 09:09, Jan Beulich wrote:
> On 07.08.2019 16:31, Juergen Gross wrote:
>> --- a/xen/Kconfig.debug
>> +++ b/xen/Kconfig.debug
>> @@ -53,6 +53,7 @@ config SPINLOCK_DEBUG
>>    
>>    config LOCK_PROFILE
>>    	bool "Lock Profiling"
>> +	select SPINLOCK_DEBUG
>>    	---help---
>>    	  Lock profiling allows you to see how often locks are taken and blocked.
>>    	  You can use serial console to print (and reset) using 'l' and 'L'
> 
> In which case, for sensible user experience, the selected
> option should come after this one. The way it is now afaict
> there'll be a prompt for SPINLOCK_DEBUG, the user may say
> "no", just to find that because of saying "yes" here it'll
> be turned on anyway. Whereas with switched ordering there'll
> be no prompt for the debug option at all (again afaict) if
> the profiling option was set to "yes".

Reordering is fine with me.


Juergen
diff mbox series

Patch

diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug
index 5db3e7ec25..a7387f1630 100644
--- a/xen/Kconfig.debug
+++ b/xen/Kconfig.debug
@@ -53,6 +53,7 @@  config SPINLOCK_DEBUG
 
 config LOCK_PROFILE
 	bool "Lock Profiling"
+	select SPINLOCK_DEBUG
 	---help---
 	  Lock profiling allows you to see how often locks are taken and blocked.
 	  You can use serial console to print (and reset) using 'l' and 'L'
diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c
index 16356ec9b7..5730076581 100644
--- a/xen/common/spinlock.c
+++ b/xen/common/spinlock.c
@@ -362,10 +362,13 @@  static void spinlock_profile_iterate(lock_profile_subfunc *sub, void *par)
 static void spinlock_profile_print_elem(struct lock_profile *data,
     int32_t type, int32_t idx, void *par)
 {
-    if ( type == LOCKPROF_TYPE_GLOBAL )
-        printk("%s %s:\n", lock_profile_ancs[type].name, data->name);
-    else
-        printk("%s %d %s:\n", lock_profile_ancs[type].name, idx, data->name);
+    struct spinlock *lock = data->lock;
+
+    printk("%s ", lock_profile_ancs[type].name);
+    if ( type != LOCKPROF_TYPE_GLOBAL )
+        printk("%d ", idx);
+    printk("%s: addr=%p, lockval=%04x, cpu=%d\n", data->name, lock,
+           lock->tickets.head_tail, lock->debug.cpu);
     printk("  lock:%12"PRId64"(%08X:%08X), block:%12"PRId64"(%08X:%08X)\n",
            data->lock_cnt, (u32)(data->time_hold >> 32), (u32)data->time_hold,
            data->block_cnt, (u32)(data->time_block >> 32),
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 1680d078db..404d28a725 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -1167,7 +1167,9 @@  void panic(const char *fmt, ...)
     unsigned long flags;
     static DEFINE_SPINLOCK(lock);
     static char buf[128];
-    
+
+    spin_debug_disable();
+    spinlock_profile_printall('\0');
     debugtrace_dump();
 
     /* Protects buf[] and ensure multi-line message prints atomically. */
diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h
index e3458f10dd..26891445fe 100644
--- a/xen/include/xen/spinlock.h
+++ b/xen/include/xen/spinlock.h
@@ -130,6 +130,7 @@  struct lock_profile_qhead { };
 #define spin_lock_init_prof(s, l) spin_lock_init(&((s)->l))
 #define lock_profile_register_struct(type, ptr, idx, print)
 #define lock_profile_deregister_struct(type, ptr)
+#define spinlock_profile_printall(key)
 
 #endif