public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] kvm tools: Fix 'kill -3' hangs
@ 2011-05-08 10:01 Pekka Enberg
  2011-05-09  7:27 ` [PATCH] kvm tools: Fix and improve the CPU register dump debug output code Ingo Molnar
  0 siblings, 1 reply; 3+ messages in thread
From: Pekka Enberg @ 2011-05-08 10:01 UTC (permalink / raw)
  To: kvm
  Cc: Pekka Enberg, Asias He, Avi Kivity, Cyrill Gorcunov, Ingo Molnar,
	Prasad Joshi, Sasha Levin

Ingo Molnar reported that 'kill -3' didn't work on his machine:

  * Ingo Molnar <mingo@elte.hu> wrote:

  > This is really cumbersome to debug - is there some good way to get to the RIP
  > that the guest is hanging in? If kvm would print that out to the host console
  > (even if it's just the raw RIP initially) on a kill -3 that would help
  > enormously.

  Looks like the code should be doing that already - but the ioctl(KVM_GET_SREGS)
  hangs:

    [pid   748] ioctl(6, KVM_GET_SREGS

Avi Kivity pointed out that it's not safe to call KVM_GET_SREGS (or other vcpu
related ioctls) from other threads:

  > is it not OK to call KVM_GET_SREGS from other threads than the one
  > that's doing KVM_RUN?

  From Documentation/kvm/api.txt:

   - vcpu ioctls: These query and set attributes that control the operation
     of a single virtual cpu.

     Only run vcpu ioctls from the same thread that was used to create the
     vcpu.

Fix that up by using pthread_kill() to force the threads that are doing KVM_RUN
to do the register dumps.

Reported: Ingo Molnar <mingo@elte.hu>
Cc: Asias He <asias.hejun@gmail.com>
Cc: Avi Kivity <avi@redhat.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Prasad Joshi <prasadjoshi124@gmail.com>
Cc: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
---
 tools/kvm/kvm-run.c |   20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index eb50b6a..58e2977 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -127,6 +127,18 @@ static const struct option options[] = {
 	OPT_END()
 };
 
+static void handle_sigusr1(int sig)
+{
+	struct kvm_cpu *cpu = current_kvm_cpu;
+
+	if (!cpu)
+		return;
+
+	kvm_cpu__show_registers(cpu);
+	kvm_cpu__show_code(cpu);
+	kvm_cpu__show_page_tables(cpu);
+}
+
 static void handle_sigquit(int sig)
 {
 	int i;
@@ -134,9 +146,10 @@ static void handle_sigquit(int sig)
 	for (i = 0; i < nrcpus; i++) {
 		struct kvm_cpu *cpu = kvm_cpus[i];
 
-		kvm_cpu__show_registers(cpu);
-		kvm_cpu__show_code(cpu);
-		kvm_cpu__show_page_tables(cpu);
+		if (!cpu)
+			continue;
+
+		pthread_kill(cpu->thread, SIGUSR1);
 	}
 
 	serial8250__inject_sysrq(kvm);
@@ -332,6 +345,7 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
 	signal(SIGALRM, handle_sigalrm);
 	signal(SIGQUIT, handle_sigquit);
+	signal(SIGUSR1, handle_sigusr1);
 
 	while (argc != 0) {
 		argc = parse_options(argc, argv, options, run_usage,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] kvm tools: Fix and improve the CPU register dump debug output code
  2011-05-08 10:01 [PATCH] kvm tools: Fix 'kill -3' hangs Pekka Enberg
@ 2011-05-09  7:27 ` Ingo Molnar
  2011-05-09  7:45   ` [PATCH] kvm tools: Dump vCPUs in order Ingo Molnar
  0 siblings, 1 reply; 3+ messages in thread
From: Ingo Molnar @ 2011-05-09  7:27 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: kvm, Asias He, Avi Kivity, Cyrill Gorcunov, Prasad Joshi,
	Sasha Levin


* Pekka Enberg <penberg@kernel.org> wrote:

> Ingo Molnar reported that 'kill -3' didn't work on his machine:
> 
>   * Ingo Molnar <mingo@elte.hu> wrote:
> 
>   > This is really cumbersome to debug - is there some good way to get to the RIP
>   > that the guest is hanging in? If kvm would print that out to the host console
>   > (even if it's just the raw RIP initially) on a kill -3 that would help
>   > enormously.
> 
>   Looks like the code should be doing that already - but the ioctl(KVM_GET_SREGS)
>   hangs:
> 
>     [pid   748] ioctl(6, KVM_GET_SREGS
> 
> Avi Kivity pointed out that it's not safe to call KVM_GET_SREGS (or other vcpu
> related ioctls) from other threads:
> 
>   > is it not OK to call KVM_GET_SREGS from other threads than the one
>   > that's doing KVM_RUN?
> 
>   From Documentation/kvm/api.txt:
> 
>    - vcpu ioctls: These query and set attributes that control the operation
>      of a single virtual cpu.
> 
>      Only run vcpu ioctls from the same thread that was used to create the
>      vcpu.
> 
> Fix that up by using pthread_kill() to force the threads that are doing KVM_RUN
> to do the register dumps.
> 
> Reported: Ingo Molnar <mingo@elte.hu>
> Cc: Asias He <asias.hejun@gmail.com>
> Cc: Avi Kivity <avi@redhat.com>
> Cc: Cyrill Gorcunov <gorcunov@gmail.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> Cc: Prasad Joshi <prasadjoshi124@gmail.com>
> Cc: Sasha Levin <levinsasha928@gmail.com>
> Signed-off-by: Pekka Enberg <penberg@kernel.org>
> ---
>  tools/kvm/kvm-run.c |   20 +++++++++++++++++---
>  1 files changed, 17 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
> index eb50b6a..58e2977 100644
> --- a/tools/kvm/kvm-run.c
> +++ b/tools/kvm/kvm-run.c
> @@ -127,6 +127,18 @@ static const struct option options[] = {
>  	OPT_END()
>  };
>  
> +static void handle_sigusr1(int sig)
> +{
> +	struct kvm_cpu *cpu = current_kvm_cpu;
> +
> +	if (!cpu)
> +		return;
> +
> +	kvm_cpu__show_registers(cpu);
> +	kvm_cpu__show_code(cpu);
> +	kvm_cpu__show_page_tables(cpu);
> +}
> +
>  static void handle_sigquit(int sig)
>  {
>  	int i;
> @@ -134,9 +146,10 @@ static void handle_sigquit(int sig)
>  	for (i = 0; i < nrcpus; i++) {
>  		struct kvm_cpu *cpu = kvm_cpus[i];
>  
> -		kvm_cpu__show_registers(cpu);
> -		kvm_cpu__show_code(cpu);
> -		kvm_cpu__show_page_tables(cpu);
> +		if (!cpu)
> +			continue;
> +
> +		pthread_kill(cpu->thread, SIGUSR1);
>  	}
>  
>  	serial8250__inject_sysrq(kvm);

i can see a couple of problems with the debug printout code, which currently 
produces a stream of such dumps for each vcpu:

Registers:
 rip: 0000000000000000   rsp: 00000000000016ca flags: 0000000000010002
 rax: 0000000000000000   rbx: 0000000000000000   rcx: 0000000000000000
 rdx: 0000000000000000   rsi: 0000000000000000   rdi: 0000000000000000
 rbp: 0000000000008000   r8:  0000000000000000   r9:  0000000000000000
 r10: 0000000000000000   r11: 0000000000000000   r12: 0000000000000000
 r13: 0000000000000000   r14: 0000000000000000   r15: 0000000000000000
 cr0: 0000000060000010   cr2: 0000000000000070   cr3: 0000000000000000
 cr4: 0000000000000000   cr8: 0000000000000000
Segment registers:
 register  selector  base              limit     type  p dpl db s l g avl
 cs        f000      00000000000f0000  0000ffff  03    1 3   0  1 0 0 0
 ss        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 ds        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 es        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 fs        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 gs        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 tr        0000      0000000000000000  0000ffff  0b    1 0   0  0 0 0 0
 ldt       0000      0000000000000000  0000ffff  02    1 0   0  0 0 0 0
 gdt                 0000000000000000 0000ffff
 idt                 0000000000000000 0000ffff
 [ efer: 0000000000000000  apic base: 00000000fee00900  nmi: enabled ]
Interrupt bitmap:
 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
Code: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <cf> eb 0d 90 90 90 90 90 90 90 90 90 90 90 90 90 f6 c4 0e 75 4b 
Stack:
  0x000016ca: 00 00 00 00  00 00 00 00
  0x000016d2: 00 00 00 00  00 00 00 00
  0x000016da: 00 00 00 00  00 00 00 00
  0x000016e2: 00 00 00 00  00 00 00 00

The problems are:

 - This does not work very well on SMP with lots of vcpus, because the printing 
   is unserialized, resulting in a jumbled mess of an output, all vcpus trying 
   to print to the console at once, often mixing lines and characters randomly.

 - stdout from a signal handler must be flushed, otherwise lines can remain 
   buffered if someone saves the output via 'tee' for example.

 - the dumps from the various CPUs are not distinguishable - they are just
   dumped after each other with no identification

 - the various printouts are rather hard to parse visually - it's not easy to see
   various properties "at a glance" because the dump is visually confusing.

The patch below addresses these concerns, serializes the output, tidies up the 
printout, resulting in this new output:

#
# vCPU #0's dump:
#

 Registers:
 ----------
 rip: 0000000000000000   rsp: 00000000000008bc flags: 0000000000010002
 rax: 0000000000000000   rbx: 0000000000000000   rcx: 0000000000000000
 rdx: 0000000000000000   rsi: 0000000000000000   rdi: 0000000000000000
 rbp: 0000000000008000    r8: 0000000000000000    r9: 0000000000000000
 r10: 0000000000000000   r11: 0000000000000000   r12: 0000000000000000
 r13: 0000000000000000   r14: 0000000000000000   r15: 0000000000000000
 cr0: 0000000060000010   cr2: 0000000000000070   cr3: 0000000000000000
 cr4: 0000000000000000   cr8: 0000000000000000

 Segment registers:
 ------------------
 register  selector  base              limit     type  p dpl db s l g avl
 cs        f000      00000000000f0000  0000ffff  03    1 3   0  1 0 0 0
 ss        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 ds        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 es        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 fs        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 gs        1000      0000000000010000  0000ffff  03    1 3   0  1 0 0 0
 tr        0000      0000000000000000  0000ffff  0b    1 0   0  0 0 0 0
 ldt       0000      0000000000000000  0000ffff  02    1 0   0  0 0 0 0
 gdt                 0000000000000000  0000ffff
 idt                 0000000000000000  0000ffff

 APIC:
 -----
 efer: 0000000000000000  apic base: 00000000fee00900  nmi: enabled

 Interrupt bitmap:
 -----------------
 0000000000000000 0000000000000000 0000000000000000 0000000000000000

 Code:
 -----
 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 <cf> eb 0d 90 90 90 90 90 90 90 90 90 90 90 90 90 f6 c4 0e 75 4b

 Stack:
 ------
  0x000008bc: 00 00 00 00  00 00 00 00
  0x000008c4: 00 00 00 00  00 00 00 00
  0x000008cc: 00 00 00 00  00 00 00 00
  0x000008d4: 00 00 00 00  00 00 00 00

Signed-off-by: Ingo Molnar <mingo@elte.hu>
---
diff --git a/tools/kvm/include/kvm/mutex.h b/tools/kvm/include/kvm/mutex.h
index 006ade3..bd765c4 100644
--- a/tools/kvm/include/kvm/mutex.h
+++ b/tools/kvm/include/kvm/mutex.h
@@ -5,6 +5,13 @@
 
 #include "kvm/util.h"
 
+/*
+ * Kernel-alike mutex API - to make it easier for kernel developers
+ * to write user-space code! :-)
+ */
+
+#define DEFINE_MUTEX(mutex) pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
+
 static inline void mutex_lock(pthread_mutex_t *mutex)
 {
 	if (pthread_mutex_lock(mutex) != 0)
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
index d7febb3..a05ee5a 100644
--- a/tools/kvm/kvm-cpu.c
+++ b/tools/kvm/kvm-cpu.c
@@ -200,7 +200,7 @@ void kvm_cpu__reset_vcpu(struct kvm_cpu *self)
 
 static void print_dtable(const char *name, struct kvm_dtable *dtable)
 {
-	printf(" %s                 %016llx %08hx\n",
+	printf(" %s                 %016llx  %08hx\n",
 		name, (u64) dtable->base, (u16) dtable->limit);
 }
 
@@ -238,11 +238,12 @@ void kvm_cpu__show_registers(struct kvm_cpu *self)
 	r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
 	r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
 
-	printf("Registers:\n");
+	printf("\n Registers:\n");
+	printf(  " ----------\n");
 	printf(" rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
 	printf(" rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
 	printf(" rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
-	printf(" rbp: %016lx   r8:  %016lx   r9:  %016lx\n", rbp, r8,  r9);
+	printf(" rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
 	printf(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
 	printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
 
@@ -254,7 +255,8 @@ void kvm_cpu__show_registers(struct kvm_cpu *self)
 
 	printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
 	printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
-	printf("Segment registers:\n");
+	printf("\n Segment registers:\n");
+	printf(  " ------------------\n");
 	printf(" register  selector  base              limit     type  p dpl db s l g avl\n");
 	print_segment("cs ", &sregs.cs);
 	print_segment("ss ", &sregs.ss);
@@ -266,13 +268,17 @@ void kvm_cpu__show_registers(struct kvm_cpu *self)
 	print_segment("ldt", &sregs.ldt);
 	print_dtable("gdt", &sregs.gdt);
 	print_dtable("idt", &sregs.idt);
-	printf(" [ efer: %016llx  apic base: %016llx  nmi: %s ]\n",
+
+	printf("\n APIC:\n");
+	printf(  " -----\n");
+	printf(" efer: %016llx  apic base: %016llx  nmi: %s\n",
 		(u64) sregs.efer, (u64) sregs.apic_base,
 		(self->kvm->nmi_disabled ? "disabled" : "enabled"));
-	printf("Interrupt bitmap:\n");
-	printf(" ");
+
+	printf("\n Interrupt bitmap:\n");
+	printf(  " -----------------\n");
 	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
-		printf("%016llx ", (u64) sregs.interrupt_bitmap[i]);
+		printf(" %016llx", (u64) sregs.interrupt_bitmap[i]);
 	printf("\n");
 }
 
@@ -293,7 +299,8 @@ void kvm_cpu__show_code(struct kvm_cpu *self)
 
 	ip = guest_flat_to_host(self->kvm, ip_to_flat(self, self->regs.rip) - code_prologue);
 
-	printf("Code: ");
+	printf("\n Code:\n");
+	printf(  " -----\n");
 
 	for (i = 0; i < code_len; i++, ip++) {
 		if (!host_ptr_in_ram(self->kvm, ip))
@@ -302,14 +309,15 @@ void kvm_cpu__show_code(struct kvm_cpu *self)
 		c = *ip;
 
 		if (ip == guest_flat_to_host(self->kvm, ip_to_flat(self, self->regs.rip)))
-			printf("<%02x> ", c);
+			printf(" <%02x>", c);
 		else
-			printf("%02x ", c);
+			printf(" %02x", c);
 	}
 
 	printf("\n");
 
-	printf("Stack:\n");
+	printf("\n Stack:\n");
+	printf(  " ------\n");
 	kvm__dump_mem(self->kvm, self->regs.rsp, 32);
 }
 
diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index 58e2977..221435d 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -29,6 +29,7 @@
 /* header files for gitish interface  */
 #include <kvm/kvm-run.h>
 #include <kvm/parse-options.h>
+#include <kvm/mutex.h>
 
 #define DEFAULT_KVM_DEV		"/dev/kvm"
 #define DEFAULT_CONSOLE		"serial"
@@ -127,6 +128,12 @@ static const struct option options[] = {
 	OPT_END()
 };
 
+/*
+ * Serialize debug printout so that the output of multiple vcpus does not
+ * get mixed up:
+ */
+static DEFINE_MUTEX(printout_mutex);
+
 static void handle_sigusr1(int sig)
 {
 	struct kvm_cpu *cpu = current_kvm_cpu;
@@ -134,9 +141,13 @@ static void handle_sigusr1(int sig)
 	if (!cpu)
 		return;
 
+	mutex_lock(&printout_mutex);
+	printf("\n#\n# vCPU #%ld's dump:\n#\n", cpu->cpu_id);
 	kvm_cpu__show_registers(cpu);
 	kvm_cpu__show_code(cpu);
 	kvm_cpu__show_page_tables(cpu);
+	fflush(stdout);
+	mutex_unlock(&printout_mutex);
 }
 
 static void handle_sigquit(int sig)

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH] kvm tools: Dump vCPUs in order
  2011-05-09  7:27 ` [PATCH] kvm tools: Fix and improve the CPU register dump debug output code Ingo Molnar
@ 2011-05-09  7:45   ` Ingo Molnar
  0 siblings, 0 replies; 3+ messages in thread
From: Ingo Molnar @ 2011-05-09  7:45 UTC (permalink / raw)
  To: Pekka Enberg
  Cc: kvm, Asias He, Avi Kivity, Cyrill Gorcunov, Prasad Joshi,
	Sasha Levin


* Ingo Molnar <mingo@elte.hu> wrote:

> The patch below addresses these concerns, serializes the output, tidies up the 
> printout, resulting in this new output:

There's one bug remaining that my patch does not address: the vCPUs are not 
printed in order:

# vCPU #0's dump:
# vCPU #2's dump:
# vCPU #24's dump:
# vCPU #5's dump:
# vCPU #39's dump:
# vCPU #38's dump:
# vCPU #51's dump:
# vCPU #11's dump:
# vCPU #10's dump:
# vCPU #12's dump:

This is undesirable as the order of printout is highly random, so successive 
dumps are difficult to compare.

The patch below serializes the signalling itself. (this is on top of the 
previous patch)

The patch also tweaks the vCPU printout line a bit so that it does not start 
with '#', which is discarded if such messages are pasted into Git commit 
messages.

Signed-off-by: Ingo Molnar <mingo@elte.hu>

diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c
index 221435d..00c70c7 100644
--- a/tools/kvm/kvm-run.c
+++ b/tools/kvm/kvm-run.c
@@ -25,6 +25,7 @@
 #include <kvm/term.h>
 #include <kvm/ioport.h>
 #include <kvm/threadpool.h>
+#include <kvm/barrier.h>
 
 /* header files for gitish interface  */
 #include <kvm/kvm-run.h>
@@ -132,7 +133,7 @@ static const struct option options[] = {
  * Serialize debug printout so that the output of multiple vcpus does not
  * get mixed up:
  */
-static DEFINE_MUTEX(printout_mutex);
+static int printout_done;
 
 static void handle_sigusr1(int sig)
 {
@@ -141,13 +142,13 @@ static void handle_sigusr1(int sig)
 	if (!cpu)
 		return;
 
-	mutex_lock(&printout_mutex);
-	printf("\n#\n# vCPU #%ld's dump:\n#\n", cpu->cpu_id);
+	printf("\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
 	kvm_cpu__show_registers(cpu);
 	kvm_cpu__show_code(cpu);
 	kvm_cpu__show_page_tables(cpu);
 	fflush(stdout);
-	mutex_unlock(&printout_mutex);
+	printout_done = 1;
+	mb();
 }
 
 static void handle_sigquit(int sig)
@@ -160,7 +161,15 @@ static void handle_sigquit(int sig)
 		if (!cpu)
 			continue;
 
+		printout_done = 0;
 		pthread_kill(cpu->thread, SIGUSR1);
+		/*
+		 * Wait for the vCPU to dump state before signalling
+		 * the next thread. Since this is debug code it does
+		 * not matter that we are burning CPU time a bit:
+		 */
+		while (!printout_done)
+			mb();
 	}
 
 	serial8250__inject_sysrq(kvm);


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-05-09  7:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-08 10:01 [PATCH] kvm tools: Fix 'kill -3' hangs Pekka Enberg
2011-05-09  7:27 ` [PATCH] kvm tools: Fix and improve the CPU register dump debug output code Ingo Molnar
2011-05-09  7:45   ` [PATCH] kvm tools: Dump vCPUs in order Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox