public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] kvm tools: Allow remapping guest TTY into host PTS
@ 2011-09-15  8:53 Sasha Levin
  2011-09-15  9:32 ` Pekka Enberg
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Sasha Levin @ 2011-09-15  8:53 UTC (permalink / raw)
  To: penberg; +Cc: kvm, mingo, asias.hejun, gorcunov, Sasha Levin, David Evensky

This patch adds the '-tty' option to 'kvm run' which allows the user to
remap a guest TTY into a PTS on the host.

Usage:
	'kvm run --tty [id] [other options]'

The tty will be mapped to a pts and will be printed on the screen:
	'  Info: Assigned terminal 1 to pty /dev/pts/X'

At this point, it is possible to communicate with the guest using that pty.

This is useful for debugging guest kernel using KGDB:

1. Run the guest:
	'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'

And see which PTY got assigned to ttyS1.

2. Run GDB on the host:
	'gdb [vmlinuz]'

3. Connect to the guest (from within GDB):
	'target remote /dev/pty/X'

4. Start debugging! (enter 'continue' to continue boot).

Cc: David Evensky <evensky@dancer.ca.sandia.gov>
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
 tools/kvm/Makefile           |    1 +
 tools/kvm/builtin-run.c      |   12 ++++++++
 tools/kvm/hw/serial.c        |   46 ++++++++++++++++++--------------
 tools/kvm/include/kvm/term.h |   11 ++++---
 tools/kvm/term.c             |   60 +++++++++++++++++++++++++++++++++--------
 tools/kvm/virtio/console.c   |    6 ++--
 6 files changed, 96 insertions(+), 40 deletions(-)

diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
index efa032d..fef624d 100644
--- a/tools/kvm/Makefile
+++ b/tools/kvm/Makefile
@@ -115,6 +115,7 @@ OBJS	+= bios/bios-rom.o
 
 LIBS	+= -lrt
 LIBS	+= -lpthread
+LIBS	+= -lutil
 
 # Additional ARCH settings for x86
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index 5dafb15..b5c63ca 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -172,6 +172,15 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
 	return 0;
 }
 
+static int tty_parser(const struct option *opt, const char *arg, int unset)
+{
+	int tty = atoi(arg);
+
+	term_set_tty(tty);
+
+	return 0;
+}
+
 static int shmem_parser(const struct option *opt, const char *arg, int unset)
 {
 	const u64 default_size = SHMEM_DEFAULT_SIZE;
@@ -316,6 +325,9 @@ static const struct option options[] = {
 	OPT_STRING('\0', "console", &console, "serial or virtio",
 			"Console to use"),
 	OPT_STRING('\0', "dev", &dev, "device_file", "KVM device file"),
+	OPT_CALLBACK('\0', "tty", NULL, "tty id",
+		     "Remap guest TTY into a pty on the host",
+		     tty_parser),
 
 	OPT_GROUP("Kernel options:"),
 	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
index b3b233f..11fa5d4 100644
--- a/tools/kvm/hw/serial.c
+++ b/tools/kvm/hw/serial.c
@@ -14,6 +14,7 @@
 
 struct serial8250_device {
 	pthread_mutex_t		mutex;
+	u8			id;
 
 	u16			iobase;
 	u8			irq;
@@ -42,6 +43,7 @@ static struct serial8250_device devices[] = {
 	[0]	= {
 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
 
+		.id			= 0,
 		.iobase			= 0x3f8,
 		.irq			= 4,
 
@@ -51,6 +53,7 @@ static struct serial8250_device devices[] = {
 	[1]	= {
 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
 
+		.id			= 1,
 		.iobase			= 0x2f8,
 		.irq			= 3,
 
@@ -60,6 +63,7 @@ static struct serial8250_device devices[] = {
 	[2]	= {
 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
 
+		.id			= 2,
 		.iobase			= 0x3e8,
 		.irq			= 4,
 
@@ -69,6 +73,7 @@ static struct serial8250_device devices[] = {
 	[3]	= {
 		.mutex			= PTHREAD_MUTEX_INITIALIZER,
 
+		.id			= 3,
 		.iobase			= 0x2e8,
 		.irq			= 3,
 
@@ -111,10 +116,10 @@ static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev)
 		return;
 	}
 
-	if (!term_readable(CONSOLE_8250))
+	if (!term_readable(CONSOLE_8250, dev->id))
 		return;
 
-	c		= term_getc(CONSOLE_8250);
+	c = term_getc(CONSOLE_8250, dev->id);
 
 	if (c < 0)
 		return;
@@ -123,30 +128,31 @@ static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev)
 	dev->lsr	|= UART_LSR_DR;
 }
 
-/*
- * Interrupts are injected for ttyS0 only.
- */
 void serial8250__inject_interrupt(struct kvm *kvm)
 {
-	struct serial8250_device *dev = &devices[0];
+	int i;
 
-	mutex_lock(&dev->mutex);
+	for (i = 0; i < 4; i++) {
+		struct serial8250_device *dev = &devices[i];
 
-	serial8250__receive(kvm, dev);
+		mutex_lock(&dev->mutex);
 
-	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
-		dev->iir		= UART_IIR_RDI;
-	else if (dev->ier & UART_IER_THRI)
-		dev->iir		= UART_IIR_THRI;
-	else
-		dev->iir		= UART_IIR_NO_INT;
+		serial8250__receive(kvm, dev);
 
-	if (dev->iir != UART_IIR_NO_INT) {
-		kvm__irq_line(kvm, dev->irq, 0);
-		kvm__irq_line(kvm, dev->irq, 1);
-	}
+		if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
+			dev->iir		= UART_IIR_RDI;
+		else if (dev->ier & UART_IER_THRI)
+			dev->iir		= UART_IIR_THRI;
+		else
+			dev->iir		= UART_IIR_NO_INT;
 
-	mutex_unlock(&dev->mutex);
+		if (dev->iir != UART_IIR_NO_INT) {
+			kvm__irq_line(kvm, dev->irq, 0);
+			kvm__irq_line(kvm, dev->irq, 1);
+		}
+
+		mutex_unlock(&dev->mutex);
+	}
 }
 
 void serial8250__inject_sysrq(struct kvm *kvm)
@@ -217,7 +223,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, voi
 			char *addr = data;
 
 			if (!(dev->mcr & UART_MCR_LOOP))
-				term_putc(CONSOLE_8250, addr, size);
+				term_putc(CONSOLE_8250, addr, size, dev->id);
 
 			dev->iir		= UART_IIR_NO_INT;
 			break;
diff --git a/tools/kvm/include/kvm/term.h b/tools/kvm/include/kvm/term.h
index 4d580e1..37ec731 100644
--- a/tools/kvm/include/kvm/term.h
+++ b/tools/kvm/include/kvm/term.h
@@ -6,12 +6,13 @@
 #define CONSOLE_8250	1
 #define CONSOLE_VIRTIO	2
 
-int term_putc_iov(int who, struct iovec *iov, int iovcnt);
-int term_getc_iov(int who, struct iovec *iov, int iovcnt);
-int term_putc(int who, char *addr, int cnt);
-int term_getc(int who);
+int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term);
+int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term);
+int term_putc(int who, char *addr, int cnt, int term);
+int term_getc(int who, int term);
 
-bool term_readable(int who);
+bool term_readable(int who, int term);
+void term_set_tty(int term);
 void term_init(void);
 
 #endif /* KVM__TERM_H */
diff --git a/tools/kvm/term.c b/tools/kvm/term.c
index fa4382d..45e8bab 100644
--- a/tools/kvm/term.c
+++ b/tools/kvm/term.c
@@ -5,6 +5,8 @@
 #include <unistd.h>
 #include <sys/uio.h>
 #include <signal.h>
+#include <pty.h>
+#include <utmp.h>
 
 #include "kvm/read-write.h"
 #include "kvm/term.h"
@@ -20,14 +22,16 @@ bool term_got_escape	= false;
 
 int active_console;
 
-int term_getc(int who)
+int term_fds[4][2];
+
+int term_getc(int who, int term)
 {
 	int c;
 
 	if (who != active_console)
 		return -1;
 
-	if (read_in_full(STDIN_FILENO, &c, 1) < 0)
+	if (read_in_full(term_fds[term][0], &c, 1) < 0)
 		return -1;
 
 	c &= 0xff;
@@ -48,26 +52,27 @@ int term_getc(int who)
 	return c;
 }
 
-int term_putc(int who, char *addr, int cnt)
+int term_putc(int who, char *addr, int cnt, int term)
 {
+	int ret;
+
 	if (who != active_console)
 		return -1;
 
 	while (cnt--)
-		fprintf(stdout, "%c", *addr++);
+		ret = write(term_fds[term][1], addr++, 1);
 
-	fflush(stdout);
 	return cnt;
 }
 
-int term_getc_iov(int who, struct iovec *iov, int iovcnt)
+int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term)
 {
 	int c;
 
 	if (who != active_console)
 		return 0;
 
-	c = term_getc(who);
+	c = term_getc(who, term);
 
 	if (c < 0)
 		return 0;
@@ -77,18 +82,18 @@ int term_getc_iov(int who, struct iovec *iov, int iovcnt)
 	return sizeof(char);
 }
 
-int term_putc_iov(int who, struct iovec *iov, int iovcnt)
+int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term)
 {
 	if (who != active_console)
 		return 0;
 
-	return writev(STDOUT_FILENO, iov, iovcnt);
+	return writev(term_fds[term][1], iov, iovcnt);
 }
 
-bool term_readable(int who)
+bool term_readable(int who, int term)
 {
 	struct pollfd pollfd = (struct pollfd) {
-		.fd	= STDIN_FILENO,
+		.fd	= term_fds[term][0],
 		.events	= POLLIN,
 		.revents = 0,
 	};
@@ -101,7 +106,10 @@ bool term_readable(int who)
 
 static void term_cleanup(void)
 {
-	tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
+	int i;
+
+	for (i = 0; i < 4; i++)
+		tcsetattr(term_fds[i][0], TCSANOW, &orig_term);
 }
 
 static void term_sig_cleanup(int sig)
@@ -111,9 +119,31 @@ static void term_sig_cleanup(int sig)
 	raise(sig);
 }
 
+void term_set_tty(int term)
+{
+	struct termios orig_term;
+	int master, slave;
+	char new_pty[PATH_MAX];
+
+	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
+		die("unable to save initial standard input settings");
+
+	orig_term.c_lflag &= ~(ICANON | ECHO | ISIG);
+
+	if (openpty(&master, &slave, new_pty, &orig_term, NULL) < 0)
+		return;
+
+	close(slave);
+
+	pr_info("Assigned terminal %d to pty %s\n", term, new_pty);
+
+	term_fds[term][0] = term_fds[term][1] = master;
+}
+
 void term_init(void)
 {
 	struct termios term;
+	int i;
 
 	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
 		die("unable to save initial standard input settings");
@@ -122,6 +152,12 @@ void term_init(void)
 	term.c_lflag &= ~(ICANON | ECHO | ISIG);
 	tcsetattr(STDIN_FILENO, TCSANOW, &term);
 
+	for (i = 0; i < 4; i++)
+		if (term_fds[i][0] == 0) {
+			term_fds[i][0] = STDIN_FILENO;
+			term_fds[i][1] = STDOUT_FILENO;
+		}
+
 	signal(SIGTERM, term_sig_cleanup);
 	atexit(term_cleanup);
 }
diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
index c0ccd6c..b880162 100644
--- a/tools/kvm/virtio/console.c
+++ b/tools/kvm/virtio/console.c
@@ -67,9 +67,9 @@ static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *par
 
 	vq = param;
 
-	if (term_readable(CONSOLE_VIRTIO) && virt_queue__available(vq)) {
+	if (term_readable(CONSOLE_VIRTIO, 0) && virt_queue__available(vq)) {
 		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
-		len = term_getc_iov(CONSOLE_VIRTIO, iov, in);
+		len = term_getc_iov(CONSOLE_VIRTIO, iov, in, 0);
 		virt_queue__set_used_elem(vq, head, len);
 		virtio_pci__signal_vq(kvm, &cdev.vpci, vq - cdev.vqs);
 	}
@@ -100,7 +100,7 @@ static void virtio_console_handle_callback(struct kvm *kvm, void *param)
 
 	while (virt_queue__available(vq)) {
 		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
-		len = term_putc_iov(CONSOLE_VIRTIO, iov, out);
+		len = term_putc_iov(CONSOLE_VIRTIO, iov, out, 0);
 		virt_queue__set_used_elem(vq, head, len);
 	}
 
-- 
1.7.6.1


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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15  8:53 [PATCH] kvm tools: Allow remapping guest TTY into host PTS Sasha Levin
@ 2011-09-15  9:32 ` Pekka Enberg
  2011-09-15 12:28   ` Sasha Levin
  2011-09-16  2:22 ` Asias He
  2011-09-18 14:30 ` Hagen Paul Pfeifer
  2 siblings, 1 reply; 7+ messages in thread
From: Pekka Enberg @ 2011-09-15  9:32 UTC (permalink / raw)
  To: Sasha Levin; +Cc: kvm, mingo, asias.hejun, gorcunov, David Evensky

On Thu, Sep 15, 2011 at 11:53 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
> This patch adds the '-tty' option to 'kvm run' which allows the user to
> remap a guest TTY into a PTS on the host.
>
> Usage:
>        'kvm run --tty [id] [other options]'
>
> The tty will be mapped to a pts and will be printed on the screen:
>        '  Info: Assigned terminal 1 to pty /dev/pts/X'
>
> At this point, it is possible to communicate with the guest using that pty.
>
> This is useful for debugging guest kernel using KGDB:
>
> 1. Run the guest:
>        'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'
>
> And see which PTY got assigned to ttyS1.
>
> 2. Run GDB on the host:
>        'gdb [vmlinuz]'
>
> 3. Connect to the guest (from within GDB):
>        'target remote /dev/pty/X'
>
> 4. Start debugging! (enter 'continue' to continue boot).
>
> Cc: David Evensky <evensky@dancer.ca.sandia.gov>
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>

Neat! Would a tools/kvm/Documentation/debugging.txt be helpful for
people who want to do kernel debugging with kvmtool?

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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15  9:32 ` Pekka Enberg
@ 2011-09-15 12:28   ` Sasha Levin
  2011-09-15 16:52     ` David Evensky
  0 siblings, 1 reply; 7+ messages in thread
From: Sasha Levin @ 2011-09-15 12:28 UTC (permalink / raw)
  To: Pekka Enberg; +Cc: kvm, mingo, asias.hejun, gorcunov, David Evensky

On Thu, 2011-09-15 at 12:32 +0300, Pekka Enberg wrote:
> On Thu, Sep 15, 2011 at 11:53 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
> > This patch adds the '-tty' option to 'kvm run' which allows the user to
> > remap a guest TTY into a PTS on the host.
> >
> > Usage:
> >        'kvm run --tty [id] [other options]'
> >
> > The tty will be mapped to a pts and will be printed on the screen:
> >        '  Info: Assigned terminal 1 to pty /dev/pts/X'
> >
> > At this point, it is possible to communicate with the guest using that pty.
> >
> > This is useful for debugging guest kernel using KGDB:
> >
> > 1. Run the guest:
> >        'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'
> >
> > And see which PTY got assigned to ttyS1.
> >
> > 2. Run GDB on the host:
> >        'gdb [vmlinuz]'
> >
> > 3. Connect to the guest (from within GDB):
> >        'target remote /dev/pty/X'
> >
> > 4. Start debugging! (enter 'continue' to continue boot).
> >
> > Cc: David Evensky <evensky@dancer.ca.sandia.gov>
> > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> 
> Neat! Would a tools/kvm/Documentation/debugging.txt be helpful for
> people who want to do kernel debugging with kvmtool?

I'll write a basic doc with the details provided above.

David, does this patch allows you to properly debug guest kernels? If
so, could you mail back any issues or hacks you had to do to set it up
so I could add it to the doc and move it into 'Documentation/'?

-- 

Sasha.


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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15 12:28   ` Sasha Levin
@ 2011-09-15 16:52     ` David Evensky
  2011-09-15 17:09       ` Sasha Levin
  0 siblings, 1 reply; 7+ messages in thread
From: David Evensky @ 2011-09-15 16:52 UTC (permalink / raw)
  To: Sasha Levin; +Cc: Pekka Enberg, kvm, mingo, asias.hejun, gorcunov


Sasha,

So far so good! I applied your patch to an older version of kvm-tool
that I had hacked on and it works for a simple test. So I think that I
can do some kernel hacking with kvm tool! Very cool.

I'm tested with the older version of kvm-tool because I am seeing a
bug with an old kernel (2.6.28.10) and the latest version of kvm-tool.
It is an old kernel, and now that I can debug more easily; hopefully I
won't require it.

In case this is worthwhile the error I'm seeing is below. While I do
have 9p compiled into my kernel, I'm not actually using it. I haven't
tried without the 9p compiled in.


$ sudo ~/.../unpatched/linux-kvm/tools/kvm/kvm run -c 1 -m 2048 -k ./bzImage-2.6.28.10 \
 --console serial -p 'console=ttyS0 ip=192.168.122.2 ' -i ./initramfs-guest.img \
  -n tap --host-ip 192.168.122.1 --guest-ip 192.168.122.2 --shmem pci:0xc8000000:16m:create

...
[    1.245232] Installing 9P2000 support
[    1.246826] 9p: virtio: Maximum channels exceeded
[    1.248674] ------------[ cut here ]------------
[    1.250291] kernel BUG at net/9p/trans_virtio.c:240!
[    1.252018] invalid opcode: 0000 [#1] SMP 
[    1.252491] last sysfs file: 
[    1.252491] Dumping ftrace buffer:
[    1.252491]    (ftrace buffer empty)
[    1.252491] CPU 0 
[    1.252491] Modules linked in:
[    1.252491] Pid: 1, comm: swapper Not tainted 2.6.28.10big_64 #6
[    1.252491] RIP: 0010:[<ffffffff8057ee2f>]  [<ffffffff8057ee2f>] p9_virtio_probe+0xcf/0x120
[    1.252491] RSP: 0018:ffff88007ec2bc90  EFLAGS: 00010286
[    1.252491] RAX: 0000000000000038 RBX: 0000000000000001 RCX: 00000000ffffffff
[    1.252491] RDX: ffffffff807d6978 RSI: 0000000000000086 RDI: 0000000000000246
[    1.252491] RBP: ffff88007d6ae800 R08: 0000000000000000 R09: 0000000000000000
[    1.252491] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88007d6ae808
[    1.252491] R13: 0000000000000000 R14: 0000000000013200 R15: 0000000000000000
[    1.252491] FS:  0000000000000000(0000) GS:ffffffff809ee000(0000) knlGS:0000000000000000
[    1.252491] CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
[    1.252491] CR2: 00007f77866892c0 CR3: 0000000000201000 CR4: 00000000000006e0
[    1.252491] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[    1.252491] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[    1.252491] Process swapper (pid: 1, threadinfo ffff88007ec2a000, task ffff88007ec29390)
[    1.252491] Stack:
[    1.252491]  ffff88007d6ae808 ffffffff804fe696 ffffffff808106e0 ffff88007d6ae800
[    1.252491]  ffff88007d6ae808 ffffffff804fe8db ffffffff808106e0 0000000000000000
[    1.252491]  ffff88007d6ae808 ffffffff8047ee3a ffffffff808106e0 ffff88007d6ae808
[    1.252491] Call Trace:
[    1.252491]  [<ffffffff804fe696>] ? add_status+0x26/0x50
[    1.252491]  [<ffffffff804fe8db>] ? virtio_dev_probe+0xab/0xf0
[    1.252491]  [<ffffffff8047ee3a>] ? driver_probe_device+0x9a/0x1b0
[    1.252491]  [<ffffffff8047eff3>] ? __driver_attach+0xa3/0xb0
[    1.252491]  [<ffffffff8047ef50>] ? __driver_attach+0x0/0xb0
[    1.252491]  [<ffffffff8047e3a8>] ? bus_for_each_dev+0x58/0x80
[    1.252491]  [<ffffffff8047e632>] ? bus_add_driver+0xb2/0x230
[    1.252491]  [<ffffffff8047f1d7>] ? driver_register+0x67/0x130
[    1.252491]  [<ffffffff8059a5cf>] ? _spin_lock+0xf/0x20
[    1.252491]  [<ffffffff80578ce2>] ? v9fs_register_trans+0x42/0x50
[    1.252491]  [<ffffffff809897ea>] ? p9_virtio_init+0x0/0x24
[    1.252491]  [<ffffffff80209042>] ? _stext+0x42/0x1c0
[    1.252491]  [<ffffffff803e40db>] ? ida_get_new_above+0x14b/0x220
[    1.252491]  [<ffffffff802ebd32>] ? kmem_cache_alloc+0x102/0x110
[    1.252491]  [<ffffffff803e431b>] ? idr_pre_get+0x4b/0x90
[    1.252491]  [<ffffffff8059a5cf>] ? _spin_lock+0xf/0x20
[    1.252491]  [<ffffffff80342d72>] ? proc_register+0x142/0x240
[    1.252491]  [<ffffffff8095ad23>] ? kernel_init+0x115/0x15d
[    1.252491]  [<ffffffff8095ad1c>] ? kernel_init+0x10e/0x15d
[    1.252491]  [<ffffffff8022eaf9>] ? child_rip+0xa/0x11
[    1.252491]  [<ffffffff8095ac0e>] ? kernel_init+0x0/0x15d
[    1.252491]  [<ffffffff8022eaef>] ? child_rip+0x0/0x11
[    1.252491] Code: 68 fa e6 ff c6 83 e1 85 b1 80 00 c6 83 e0 85 b1 80 01 31 c0 48 83 c4 10 5b 5d 41 5c c3 48 c7 c7 e0 42 6e 80 3                                 
1 c0 e8 0b 8b 01 00 <0f> 0b eb fe 48 8b 95 78 02 00 00 48 89 c7 48 89 44 24 08 ff 52 
[    1.252491] RIP  [<ffffffff8057ee2f>] p9_virtio_probe+0xcf/0x120
[    1.252491]  RSP <ffff88007ec2bc90>
[    1.360254] ---[ end trace 695d68cac3254cff ]---
[    1.361863] Kernel panic - not syncing: Attempted to kill init!
[    1.364043] Rebooting in 1 seconds..

*** Compatability Warning ***

        virtio-9p device was not detected

While you have requested a virtio-9p device, the guest kernel didn't seem to detect it.
Please make sure that the kernel was compiled with CONFIG_NET_9P_VIRTIO.

  # KVM session ended normally.


For this kernel, CONFIG_NET_9P_VIRTIO is defined, but the kernel is old, so
there may be issues.

\dae

On Thu, Sep 15, 2011 at 03:28:46PM +0300, Sasha Levin wrote:
> On Thu, 2011-09-15 at 12:32 +0300, Pekka Enberg wrote:
> > On Thu, Sep 15, 2011 at 11:53 AM, Sasha Levin <levinsasha928@gmail.com> wrote:
> > > This patch adds the '-tty' option to 'kvm run' which allows the user to
> > > remap a guest TTY into a PTS on the host.
> > >
> > > Usage:
> > >        'kvm run --tty [id] [other options]'
> > >
> > > The tty will be mapped to a pts and will be printed on the screen:
> > >        '  Info: Assigned terminal 1 to pty /dev/pts/X'
> > >
> > > At this point, it is possible to communicate with the guest using that pty.
> > >
> > > This is useful for debugging guest kernel using KGDB:
> > >
> > > 1. Run the guest:
> > >        'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'
> > >
> > > And see which PTY got assigned to ttyS1.
> > >
> > > 2. Run GDB on the host:
> > >        'gdb [vmlinuz]'
> > >
> > > 3. Connect to the guest (from within GDB):
> > >        'target remote /dev/pty/X'
> > >
> > > 4. Start debugging! (enter 'continue' to continue boot).
> > >
> > > Cc: David Evensky <evensky@dancer.ca.sandia.gov>
> > > Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> > 
> > Neat! Would a tools/kvm/Documentation/debugging.txt be helpful for
> > people who want to do kernel debugging with kvmtool?
> 
> I'll write a basic doc with the details provided above.
> 
> David, does this patch allows you to properly debug guest kernels? If
> so, could you mail back any issues or hacks you had to do to set it up
> so I could add it to the doc and move it into 'Documentation/'?
> 
> -- 
> 
> Sasha.
> 

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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15 16:52     ` David Evensky
@ 2011-09-15 17:09       ` Sasha Levin
  0 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2011-09-15 17:09 UTC (permalink / raw)
  To: David Evensky; +Cc: Pekka Enberg, kvm, mingo, asias.hejun, gorcunov

On Thu, 2011-09-15 at 09:52 -0700, David Evensky wrote:
> Sasha,
> 
> So far so good! I applied your patch to an older version of kvm-tool
> that I had hacked on and it works for a simple test. So I think that I
> can do some kernel hacking with kvm tool! Very cool.
> 

Awesome!

> I'm tested with the older version of kvm-tool because I am seeing a
> bug with an old kernel (2.6.28.10) and the latest version of kvm-tool.
> It is an old kernel, and now that I can debug more easily; hopefully I
> won't require it.
> 
> In case this is worthwhile the error I'm seeing is below. While I do
> have 9p compiled into my kernel, I'm not actually using it. I haven't
> tried without the 9p compiled in.
> 

[snip]

> For this kernel, CONFIG_NET_9P_VIRTIO is defined, but the kernel is old, so
> there may be issues.
> 
> \dae
> 

I've noticed that 9p/virtio-9p is a bit unstable in older versions, for
example: you can't use 9p rootfs with kernels older than 2.6.38 (which
isn't that old really).

-- 

Sasha.


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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15  8:53 [PATCH] kvm tools: Allow remapping guest TTY into host PTS Sasha Levin
  2011-09-15  9:32 ` Pekka Enberg
@ 2011-09-16  2:22 ` Asias He
  2011-09-18 14:30 ` Hagen Paul Pfeifer
  2 siblings, 0 replies; 7+ messages in thread
From: Asias He @ 2011-09-16  2:22 UTC (permalink / raw)
  To: Sasha Levin; +Cc: Pekka Enberg, kvm, mingo, gorcunov, David Evensky

On 09/15/2011 04:53 PM, Sasha Levin wrote:
> This patch adds the '-tty' option to 'kvm run' which allows the user to
> remap a guest TTY into a PTS on the host.
> 
> Usage:
> 	'kvm run --tty [id] [other options]'
> 
> The tty will be mapped to a pts and will be printed on the screen:
> 	'  Info: Assigned terminal 1 to pty /dev/pts/X'
> 
> At this point, it is possible to communicate with the guest using that pty.
> 
> This is useful for debugging guest kernel using KGDB:
> 
> 1. Run the guest:
> 	'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'
> 
> And see which PTY got assigned to ttyS1.
> 
> 2. Run GDB on the host:
> 	'gdb [vmlinuz]'
> 
> 3. Connect to the guest (from within GDB):
> 	'target remote /dev/pty/X'
> 
> 4. Start debugging! (enter 'continue' to continue boot).
> 
> Cc: David Evensky <evensky@dancer.ca.sandia.gov>
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> ---
>  tools/kvm/Makefile           |    1 +
>  tools/kvm/builtin-run.c      |   12 ++++++++
>  tools/kvm/hw/serial.c        |   46 ++++++++++++++++++--------------
>  tools/kvm/include/kvm/term.h |   11 ++++---
>  tools/kvm/term.c             |   60 +++++++++++++++++++++++++++++++++--------
>  tools/kvm/virtio/console.c   |    6 ++--
>  6 files changed, 96 insertions(+), 40 deletions(-)
> 
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index efa032d..fef624d 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -115,6 +115,7 @@ OBJS	+= bios/bios-rom.o
>  
>  LIBS	+= -lrt
>  LIBS	+= -lpthread
> +LIBS	+= -lutil
>  
>  # Additional ARCH settings for x86
>  ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
> diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
> index 5dafb15..b5c63ca 100644
> --- a/tools/kvm/builtin-run.c
> +++ b/tools/kvm/builtin-run.c
> @@ -172,6 +172,15 @@ static int virtio_9p_rootdir_parser(const struct option *opt, const char *arg, i
>  	return 0;
>  }
>  
> +static int tty_parser(const struct option *opt, const char *arg, int unset)
> +{
> +	int tty = atoi(arg);
> +
> +	term_set_tty(tty);
> +
> +	return 0;
> +}
> +
>  static int shmem_parser(const struct option *opt, const char *arg, int unset)
>  {
>  	const u64 default_size = SHMEM_DEFAULT_SIZE;
> @@ -316,6 +325,9 @@ static const struct option options[] = {
>  	OPT_STRING('\0', "console", &console, "serial or virtio",
>  			"Console to use"),
>  	OPT_STRING('\0', "dev", &dev, "device_file", "KVM device file"),
> +	OPT_CALLBACK('\0', "tty", NULL, "tty id",
> +		     "Remap guest TTY into a pty on the host",
> +		     tty_parser),
>  
>  	OPT_GROUP("Kernel options:"),
>  	OPT_STRING('k', "kernel", &kernel_filename, "kernel",
> diff --git a/tools/kvm/hw/serial.c b/tools/kvm/hw/serial.c
> index b3b233f..11fa5d4 100644
> --- a/tools/kvm/hw/serial.c
> +++ b/tools/kvm/hw/serial.c
> @@ -14,6 +14,7 @@
>  
>  struct serial8250_device {
>  	pthread_mutex_t		mutex;
> +	u8			id;
>  
>  	u16			iobase;
>  	u8			irq;
> @@ -42,6 +43,7 @@ static struct serial8250_device devices[] = {
>  	[0]	= {
>  		.mutex			= PTHREAD_MUTEX_INITIALIZER,
>  
> +		.id			= 0,
>  		.iobase			= 0x3f8,
>  		.irq			= 4,
>  
> @@ -51,6 +53,7 @@ static struct serial8250_device devices[] = {
>  	[1]	= {
>  		.mutex			= PTHREAD_MUTEX_INITIALIZER,
>  
> +		.id			= 1,
>  		.iobase			= 0x2f8,
>  		.irq			= 3,
>  
> @@ -60,6 +63,7 @@ static struct serial8250_device devices[] = {
>  	[2]	= {
>  		.mutex			= PTHREAD_MUTEX_INITIALIZER,
>  
> +		.id			= 2,
>  		.iobase			= 0x3e8,
>  		.irq			= 4,
>  
> @@ -69,6 +73,7 @@ static struct serial8250_device devices[] = {
>  	[3]	= {
>  		.mutex			= PTHREAD_MUTEX_INITIALIZER,
>  
> +		.id			= 3,
>  		.iobase			= 0x2e8,
>  		.irq			= 3,
>  
> @@ -111,10 +116,10 @@ static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev)
>  		return;
>  	}
>  
> -	if (!term_readable(CONSOLE_8250))
> +	if (!term_readable(CONSOLE_8250, dev->id))
>  		return;
>  
> -	c		= term_getc(CONSOLE_8250);
> +	c = term_getc(CONSOLE_8250, dev->id);
>  
>  	if (c < 0)
>  		return;
> @@ -123,30 +128,31 @@ static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev)
>  	dev->lsr	|= UART_LSR_DR;
>  }
>  
> -/*
> - * Interrupts are injected for ttyS0 only.
> - */
>  void serial8250__inject_interrupt(struct kvm *kvm)
>  {
> -	struct serial8250_device *dev = &devices[0];
> +	int i;
>  
> -	mutex_lock(&dev->mutex);
> +	for (i = 0; i < 4; i++) {
> +		struct serial8250_device *dev = &devices[i];
>  
> -	serial8250__receive(kvm, dev);
> +		mutex_lock(&dev->mutex);
>  
> -	if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
> -		dev->iir		= UART_IIR_RDI;
> -	else if (dev->ier & UART_IER_THRI)
> -		dev->iir		= UART_IIR_THRI;
> -	else
> -		dev->iir		= UART_IIR_NO_INT;
> +		serial8250__receive(kvm, dev);
>  
> -	if (dev->iir != UART_IIR_NO_INT) {
> -		kvm__irq_line(kvm, dev->irq, 0);
> -		kvm__irq_line(kvm, dev->irq, 1);
> -	}
> +		if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR)
> +			dev->iir		= UART_IIR_RDI;
> +		else if (dev->ier & UART_IER_THRI)
> +			dev->iir		= UART_IIR_THRI;
> +		else
> +			dev->iir		= UART_IIR_NO_INT;
>  
> -	mutex_unlock(&dev->mutex);
> +		if (dev->iir != UART_IIR_NO_INT) {
> +			kvm__irq_line(kvm, dev->irq, 0);
> +			kvm__irq_line(kvm, dev->irq, 1);
> +		}
> +
> +		mutex_unlock(&dev->mutex);
> +	}
>  }
>  
>  void serial8250__inject_sysrq(struct kvm *kvm)
> @@ -217,7 +223,7 @@ static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, voi
>  			char *addr = data;
>  
>  			if (!(dev->mcr & UART_MCR_LOOP))
> -				term_putc(CONSOLE_8250, addr, size);
> +				term_putc(CONSOLE_8250, addr, size, dev->id);
>  
>  			dev->iir		= UART_IIR_NO_INT;
>  			break;
> diff --git a/tools/kvm/include/kvm/term.h b/tools/kvm/include/kvm/term.h
> index 4d580e1..37ec731 100644
> --- a/tools/kvm/include/kvm/term.h
> +++ b/tools/kvm/include/kvm/term.h
> @@ -6,12 +6,13 @@
>  #define CONSOLE_8250	1
>  #define CONSOLE_VIRTIO	2
>  
> -int term_putc_iov(int who, struct iovec *iov, int iovcnt);
> -int term_getc_iov(int who, struct iovec *iov, int iovcnt);
> -int term_putc(int who, char *addr, int cnt);
> -int term_getc(int who);
> +int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term);
> +int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term);
> +int term_putc(int who, char *addr, int cnt, int term);
> +int term_getc(int who, int term);
>  
> -bool term_readable(int who);
> +bool term_readable(int who, int term);
> +void term_set_tty(int term);
>  void term_init(void);
>  
>  #endif /* KVM__TERM_H */
> diff --git a/tools/kvm/term.c b/tools/kvm/term.c
> index fa4382d..45e8bab 100644
> --- a/tools/kvm/term.c
> +++ b/tools/kvm/term.c
> @@ -5,6 +5,8 @@
>  #include <unistd.h>
>  #include <sys/uio.h>
>  #include <signal.h>
> +#include <pty.h>
> +#include <utmp.h>
>  
>  #include "kvm/read-write.h"
>  #include "kvm/term.h"
> @@ -20,14 +22,16 @@ bool term_got_escape	= false;
>  
>  int active_console;
>  
> -int term_getc(int who)
> +int term_fds[4][2];
> +
> +int term_getc(int who, int term)
>  {
>  	int c;
>  
>  	if (who != active_console)
>  		return -1;
>  
> -	if (read_in_full(STDIN_FILENO, &c, 1) < 0)
> +	if (read_in_full(term_fds[term][0], &c, 1) < 0)

We need a Macro like:

#define TERM_FD_IN	0
#define TERM_FD_OUT	1

>  		return -1;
>  
>  	c &= 0xff;
> @@ -48,26 +52,27 @@ int term_getc(int who)
>  	return c;
>  }
>  
> -int term_putc(int who, char *addr, int cnt)
> +int term_putc(int who, char *addr, int cnt, int term)
>  {
> +	int ret;
> +
>  	if (who != active_console)
>  		return -1;
>  
>  	while (cnt--)
> -		fprintf(stdout, "%c", *addr++);
> +		ret = write(term_fds[term][1], addr++, 1);

Here and some other places too.

And I am seeing:

term.c: In function ‘term_putc’:
term.c:57:6: error: variable ‘ret’ set but not used
[-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors


> -	fflush(stdout);
>  	return cnt;
>  }
>  
> -int term_getc_iov(int who, struct iovec *iov, int iovcnt)
> +int term_getc_iov(int who, struct iovec *iov, int iovcnt, int term)
>  {
>  	int c;
>  
>  	if (who != active_console)
>  		return 0;
>  
> -	c = term_getc(who);
> +	c = term_getc(who, term);
>  
>  	if (c < 0)
>  		return 0;
> @@ -77,18 +82,18 @@ int term_getc_iov(int who, struct iovec *iov, int iovcnt)
>  	return sizeof(char);
>  }
>  
> -int term_putc_iov(int who, struct iovec *iov, int iovcnt)
> +int term_putc_iov(int who, struct iovec *iov, int iovcnt, int term)
>  {
>  	if (who != active_console)
>  		return 0;
>  
> -	return writev(STDOUT_FILENO, iov, iovcnt);
> +	return writev(term_fds[term][1], iov, iovcnt);
>  }
>  
> -bool term_readable(int who)
> +bool term_readable(int who, int term)
>  {
>  	struct pollfd pollfd = (struct pollfd) {
> -		.fd	= STDIN_FILENO,
> +		.fd	= term_fds[term][0],
>  		.events	= POLLIN,
>  		.revents = 0,
>  	};
> @@ -101,7 +106,10 @@ bool term_readable(int who)
>  
>  static void term_cleanup(void)
>  {
> -	tcsetattr(STDIN_FILENO, TCSANOW, &orig_term);
> +	int i;
> +
> +	for (i = 0; i < 4; i++)
> +		tcsetattr(term_fds[i][0], TCSANOW, &orig_term);
>  }
>  
>  static void term_sig_cleanup(int sig)
> @@ -111,9 +119,31 @@ static void term_sig_cleanup(int sig)
>  	raise(sig);
>  }
>  
> +void term_set_tty(int term)
> +{
> +	struct termios orig_term;
> +	int master, slave;
> +	char new_pty[PATH_MAX];
> +
> +	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
> +		die("unable to save initial standard input settings");
> +
> +	orig_term.c_lflag &= ~(ICANON | ECHO | ISIG);
> +
> +	if (openpty(&master, &slave, new_pty, &orig_term, NULL) < 0)
> +		return;
> +
> +	close(slave);
> +
> +	pr_info("Assigned terminal %d to pty %s\n", term, new_pty);
> +
> +	term_fds[term][0] = term_fds[term][1] = master;
> +}
> +
>  void term_init(void)
>  {
>  	struct termios term;
> +	int i;
>  
>  	if (tcgetattr(STDIN_FILENO, &orig_term) < 0)
>  		die("unable to save initial standard input settings");
> @@ -122,6 +152,12 @@ void term_init(void)
>  	term.c_lflag &= ~(ICANON | ECHO | ISIG);
>  	tcsetattr(STDIN_FILENO, TCSANOW, &term);
>  
> +	for (i = 0; i < 4; i++)
> +		if (term_fds[i][0] == 0) {
> +			term_fds[i][0] = STDIN_FILENO;
> +			term_fds[i][1] = STDOUT_FILENO;
> +		}
> +
>  	signal(SIGTERM, term_sig_cleanup);
>  	atexit(term_cleanup);
>  }
> diff --git a/tools/kvm/virtio/console.c b/tools/kvm/virtio/console.c
> index c0ccd6c..b880162 100644
> --- a/tools/kvm/virtio/console.c
> +++ b/tools/kvm/virtio/console.c
> @@ -67,9 +67,9 @@ static void virtio_console__inject_interrupt_callback(struct kvm *kvm, void *par
>  
>  	vq = param;
>  
> -	if (term_readable(CONSOLE_VIRTIO) && virt_queue__available(vq)) {
> +	if (term_readable(CONSOLE_VIRTIO, 0) && virt_queue__available(vq)) {
>  		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
> -		len = term_getc_iov(CONSOLE_VIRTIO, iov, in);
> +		len = term_getc_iov(CONSOLE_VIRTIO, iov, in, 0);
>  		virt_queue__set_used_elem(vq, head, len);
>  		virtio_pci__signal_vq(kvm, &cdev.vpci, vq - cdev.vqs);
>  	}
> @@ -100,7 +100,7 @@ static void virtio_console_handle_callback(struct kvm *kvm, void *param)
>  
>  	while (virt_queue__available(vq)) {
>  		head = virt_queue__get_iov(vq, iov, &out, &in, kvm);
> -		len = term_putc_iov(CONSOLE_VIRTIO, iov, out);
> +		len = term_putc_iov(CONSOLE_VIRTIO, iov, out, 0);
>  		virt_queue__set_used_elem(vq, head, len);
>  	}
>  

-- 
Asias He

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

* Re: [PATCH] kvm tools: Allow remapping guest TTY into host PTS
  2011-09-15  8:53 [PATCH] kvm tools: Allow remapping guest TTY into host PTS Sasha Levin
  2011-09-15  9:32 ` Pekka Enberg
  2011-09-16  2:22 ` Asias He
@ 2011-09-18 14:30 ` Hagen Paul Pfeifer
  2 siblings, 0 replies; 7+ messages in thread
From: Hagen Paul Pfeifer @ 2011-09-18 14:30 UTC (permalink / raw)
  To: Sasha Levin; +Cc: penberg, kvm, mingo, asias.hejun, gorcunov, David Evensky

* Sasha Levin | 2011-09-15 11:53:10 [+0300]:

>1. Run the guest:
>	'kvm run -k [vmlinuz] -p "kdbgoc=ttyS1 kdbgwait" --tty 1'
                            kgdboc       kgdbwait


>4. Start debugging! (enter 'continue' to continue boot).
>
>Cc: David Evensky <evensky@dancer.ca.sandia.gov>
>Signed-off-by: Sasha Levin <levinsasha928@gmail.com>

Tested-by: Hagen Paul Pfeifer <hagen@jauu.net>

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

end of thread, other threads:[~2011-09-18 14:30 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-09-15  8:53 [PATCH] kvm tools: Allow remapping guest TTY into host PTS Sasha Levin
2011-09-15  9:32 ` Pekka Enberg
2011-09-15 12:28   ` Sasha Levin
2011-09-15 16:52     ` David Evensky
2011-09-15 17:09       ` Sasha Levin
2011-09-16  2:22 ` Asias He
2011-09-18 14:30 ` Hagen Paul Pfeifer

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