[PATCH v3] kvm tools: Allow piping debug output to file descriptor

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch makes debug output go to a 'debug_fd' instead of stdout.

Doing so allows us to send the output to a different console when
required.

This patch also changes the behaviour of 'kvm debug' to show the debug
output in the console that executed the debug command instead of in the
console of the guest.

Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx>
---
 tools/kvm/builtin-debug.c       |   13 ++++++-
 tools/kvm/builtin-run.c         |    8 +++-
 tools/kvm/include/kvm/kvm-cpu.h |    2 +
 tools/kvm/kvm-cpu.c             |   78 ++++++++++++++++++++++----------------
 4 files changed, 66 insertions(+), 35 deletions(-)

diff --git a/tools/kvm/builtin-debug.c b/tools/kvm/builtin-debug.c
index f744a7e..045dc2c 100644
--- a/tools/kvm/builtin-debug.c
+++ b/tools/kvm/builtin-debug.c
@@ -4,11 +4,14 @@
 #include <kvm/kvm.h>
 #include <kvm/parse-options.h>
 #include <kvm/kvm-ipc.h>
+#include <kvm/read-write.h>
 
 #include <stdio.h>
 #include <string.h>
 #include <signal.h>
 
+#define BUFFER_SIZE 100
+
 static bool all;
 static int instance;
 static const char *instance_name;
@@ -47,13 +50,21 @@ void kvm_debug_help(void)
 
 static int do_debug(const char *name, int sock)
 {
+	char buff[BUFFER_SIZE];
 	struct debug_cmd cmd = {KVM_IPC_DEBUG, 0};
 	int r;
 
-	r = write(sock, &cmd, sizeof(cmd));
+	r = xwrite(sock, &cmd, sizeof(cmd));
 	if (r < 0)
 		return r;
 
+	do {
+		r = xread(sock, buff, BUFFER_SIZE);
+		if (r < 0)
+			return 0;
+		printf("%.*s", r, buff);
+	} while (r > 0);
+
 	return 0;
 }
 
diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index bbe5a35..2792650 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -456,11 +456,12 @@ static int printout_done;
 static void handle_sigusr1(int sig)
 {
 	struct kvm_cpu *cpu = current_kvm_cpu;
+	int fd = kvm_cpu__get_debug_fd();
 
 	if (!cpu)
 		return;
 
-	printf("\n #\n # vCPU #%ld's dump:\n #\n", cpu->cpu_id);
+	dprintf(fd, "\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);
@@ -496,6 +497,8 @@ static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
 			continue;
 
 		printout_done = 0;
+
+		kvm_cpu__set_debug_fd(fd);
 		pthread_kill(cpu->thread, SIGUSR1);
 		/*
 		 * Wait for the vCPU to dump state before signalling
@@ -506,6 +509,8 @@ static void handle_debug(int fd, u32 type, u32 len, u8 *msg)
 			mb();
 	}
 
+	close(fd);
+
 	serial8250__inject_sysrq(kvm);
 }
 
@@ -539,6 +544,7 @@ panic_kvm:
 		fprintf(stderr, "KVM exit code: 0x%Lu\n",
 			current_kvm_cpu->kvm_run->hw.hardware_exit_reason);
 
+	kvm_cpu__set_debug_fd(STDOUT_FILENO);
 	kvm_cpu__show_registers(current_kvm_cpu);
 	kvm_cpu__show_code(current_kvm_cpu);
 	kvm_cpu__show_page_tables(current_kvm_cpu);
diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h
index 95f3f9d..01540ac 100644
--- a/tools/kvm/include/kvm/kvm-cpu.h
+++ b/tools/kvm/include/kvm/kvm-cpu.h
@@ -37,6 +37,8 @@ void kvm_cpu__run(struct kvm_cpu *vcpu);
 void kvm_cpu__reboot(void);
 int kvm_cpu__start(struct kvm_cpu *cpu);
 
+int kvm_cpu__get_debug_fd(void);
+void kvm_cpu__set_debug_fd(int fd);
 void kvm_cpu__show_code(struct kvm_cpu *vcpu);
 void kvm_cpu__show_registers(struct kvm_cpu *vcpu);
 void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu);
diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c
index d7ae5ce..0ad6f3b 100644
--- a/tools/kvm/kvm-cpu.c
+++ b/tools/kvm/kvm-cpu.c
@@ -19,6 +19,18 @@
 extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS];
 extern __thread struct kvm_cpu *current_kvm_cpu;
 
+static int debug_fd;
+
+void kvm_cpu__set_debug_fd(int fd)
+{
+	debug_fd = fd;
+}
+
+int kvm_cpu__get_debug_fd(void)
+{
+	return debug_fd;
+}
+
 static inline bool is_in_protected_mode(struct kvm_cpu *vcpu)
 {
 	return vcpu->sregs.cr0 & 0x01;
@@ -216,13 +228,13 @@ void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
 
 static void print_dtable(const char *name, struct kvm_dtable *dtable)
 {
-	printf(" %s                 %016llx  %08hx\n",
+	dprintf(debug_fd, " %s                 %016llx  %08hx\n",
 		name, (u64) dtable->base, (u16) dtable->limit);
 }
 
 static void print_segment(const char *name, struct kvm_segment *seg)
 {
-	printf(" %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
+	dprintf(debug_fd, " %s       %04hx      %016llx  %08x  %02hhx    %x %x   %x  %x %x %x %x\n",
 		name, (u16) seg->selector, (u64) seg->base, (u32) seg->limit,
 		(u8) seg->type, seg->present, seg->dpl, seg->db, seg->s, seg->l, seg->g, seg->avl);
 }
@@ -254,14 +266,14 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 	r10 = regs.r10; r11 = regs.r11; r12 = regs.r12;
 	r13 = regs.r13; r14 = regs.r14; r15 = regs.r15;
 
-	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(" r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
-	printf(" r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
+	dprintf(debug_fd, "\n Registers:\n");
+	dprintf(debug_fd,   " ----------\n");
+	dprintf(debug_fd, " rip: %016lx   rsp: %016lx flags: %016lx\n", rip, rsp, rflags);
+	dprintf(debug_fd, " rax: %016lx   rbx: %016lx   rcx: %016lx\n", rax, rbx, rcx);
+	dprintf(debug_fd, " rdx: %016lx   rsi: %016lx   rdi: %016lx\n", rdx, rsi, rdi);
+	dprintf(debug_fd, " rbp: %016lx    r8: %016lx    r9: %016lx\n", rbp, r8,  r9);
+	dprintf(debug_fd, " r10: %016lx   r11: %016lx   r12: %016lx\n", r10, r11, r12);
+	dprintf(debug_fd, " r13: %016lx   r14: %016lx   r15: %016lx\n", r13, r14, r15);
 
 	if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
 		die("KVM_GET_REGS failed");
@@ -269,11 +281,11 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 	cr0 = sregs.cr0; cr2 = sregs.cr2; cr3 = sregs.cr3;
 	cr4 = sregs.cr4; cr8 = sregs.cr8;
 
-	printf(" cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
-	printf(" cr4: %016lx   cr8: %016lx\n", cr4, cr8);
-	printf("\n Segment registers:\n");
-	printf(  " ------------------\n");
-	printf(" register  selector  base              limit     type  p dpl db s l g avl\n");
+	dprintf(debug_fd, " cr0: %016lx   cr2: %016lx   cr3: %016lx\n", cr0, cr2, cr3);
+	dprintf(debug_fd, " cr4: %016lx   cr8: %016lx\n", cr4, cr8);
+	dprintf(debug_fd, "\n Segment registers:\n");
+	dprintf(debug_fd,   " ------------------\n");
+	dprintf(debug_fd, " register  selector  base              limit     type  p dpl db s l g avl\n");
 	print_segment("cs ", &sregs.cs);
 	print_segment("ss ", &sregs.ss);
 	print_segment("ds ", &sregs.ds);
@@ -285,17 +297,17 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 	print_dtable("gdt", &sregs.gdt);
 	print_dtable("idt", &sregs.idt);
 
-	printf("\n APIC:\n");
-	printf(  " -----\n");
-	printf(" efer: %016llx  apic base: %016llx  nmi: %s\n",
+	dprintf(debug_fd, "\n APIC:\n");
+	dprintf(debug_fd,   " -----\n");
+	dprintf(debug_fd, " efer: %016llx  apic base: %016llx  nmi: %s\n",
 		(u64) sregs.efer, (u64) sregs.apic_base,
 		(vcpu->kvm->nmi_disabled ? "disabled" : "enabled"));
 
-	printf("\n Interrupt bitmap:\n");
-	printf(  " -----------------\n");
+	dprintf(debug_fd, "\n Interrupt bitmap:\n");
+	dprintf(debug_fd,   " -----------------\n");
 	for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++)
-		printf(" %016llx", (u64) sregs.interrupt_bitmap[i]);
-	printf("\n");
+		dprintf(debug_fd, " %016llx", (u64) sregs.interrupt_bitmap[i]);
+	dprintf(debug_fd, "\n");
 }
 
 #define MAX_SYM_LEN		128
@@ -318,12 +330,12 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu)
 
 	ip = guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip) - code_prologue);
 
-	printf("\n Code:\n");
-	printf(  " -----\n");
+	dprintf(debug_fd, "\n Code:\n");
+	dprintf(debug_fd,   " -----\n");
 
 	symbol__lookup(vcpu->kvm, vcpu->regs.rip, sym, MAX_SYM_LEN);
 
-	printf(" rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
+	dprintf(debug_fd, " rip: [<%016lx>] %s\n\n", (unsigned long) vcpu->regs.rip, sym);
 
 	for (i = 0; i < code_len; i++, ip++) {
 		if (!host_ptr_in_ram(vcpu->kvm, ip))
@@ -332,15 +344,15 @@ void kvm_cpu__show_code(struct kvm_cpu *vcpu)
 		c = *ip;
 
 		if (ip == guest_flat_to_host(vcpu->kvm, ip_to_flat(vcpu, vcpu->regs.rip)))
-			printf(" <%02x>", c);
+			dprintf(debug_fd, " <%02x>", c);
 		else
-			printf(" %02x", c);
+			dprintf(debug_fd, " %02x", c);
 	}
 
-	printf("\n");
+	dprintf(debug_fd, "\n");
 
-	printf("\n Stack:\n");
-	printf(  " ------\n");
+	dprintf(debug_fd, "\n Stack:\n");
+	dprintf(debug_fd,   " ------\n");
 	kvm__dump_mem(vcpu->kvm, vcpu->regs.rsp, 32);
 }
 
@@ -373,13 +385,13 @@ void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
 	if (!host_ptr_in_ram(vcpu->kvm, pte1))
 		return;
 
-	printf("Page Tables:\n");
+	dprintf(debug_fd, "Page Tables:\n");
 	if (*pte2 & (1 << 7))
-		printf(" pte4: %016llx   pte3: %016llx"
+		dprintf(debug_fd, " pte4: %016llx   pte3: %016llx"
 			"   pte2: %016llx\n",
 			*pte4, *pte3, *pte2);
 	else
-		printf(" pte4: %016llx  pte3: %016llx   pte2: %016"
+		dprintf(debug_fd, " pte4: %016llx  pte3: %016llx   pte2: %016"
 			"llx   pte1: %016llx\n",
 			*pte4, *pte3, *pte2, *pte1);
 }
-- 
1.7.7

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux