Miche Baker-Harvey
2011-Nov-08 21:44 UTC
[PATCH RFC v3 0/3] Support multiple VirtioConsoles.
(Amit pointed out that the patches never went out. This was a resend of the series meant to go out on 11/2/2011; Now it's a resend of the mail this morning, with everyone copied on the same mail. So sorry for the spam! This is v3.) This patchset applies to linux-next/next-20111102. This series implements support for multiple virtio_consoles using KVM. This patchset addresses several issues associated with trying to establish multiple virtio consoles. I'm trying to start a guest via KVM that supports multiple virtual consoles, with getty's on each, and with some being console devices. These patches let me establish more than one VirtioConsole (I'm running eight at the moment), and enable console output appearing on one of them. It still doesn't successfully generate console output on multiple VirtioConsoles. Let me apologise for my last patch having gotten into Linus' tree, and leaving other people to deal with crashes. I had meant to be asking for guidance, but I didn't mark it as "RFC". This series reflects the input from Konrad Rzeszutek, Amit Shah, Stephen Boyd, and Rusty Russell. I think we do have to limit hvc_alloc() to one thread. I would appreciate any comments or feedback, or accept if appropriate. Thanks, Miche Baker-Harvey --- Miche Baker-Harvey (3): virtio_console: Fix locking of vtermno. hvc_init(): Enforce one-time initialization. Use separate struct console structure for each hvc_console. drivers/char/virtio_console.c | 9 ++++++--- drivers/tty/hvc/hvc_console.c | 33 +++++++++++++++++++++++++++++++-- drivers/tty/hvc/hvc_console.h | 1 + 3 files changed, 38 insertions(+), 5 deletions(-) --
Miche Baker-Harvey
2011-Nov-08 21:44 UTC
[PATCH v3 1/3] virtio_console: Fix locking of vtermno.
Some modifications of vtermno were not done under the spinlock. Moved assignment from vtermno and increment of vtermno together, putting both under the spinlock. Revert vtermno on failure. Signed-off-by: Miche Baker-Harvey <miche at google.com> --- drivers/char/virtio_console.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8e3c46d..9722e76 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -987,18 +987,21 @@ int init_port_console(struct port *port) * pointers. The final argument is the output buffer size: we * can do any size, so we put PAGE_SIZE here. */ - port->cons.vtermno = pdrvdata.next_vtermno; + spin_lock_irq(&pdrvdata_lock); + port->cons.vtermno = pdrvdata.next_vtermno++; + spin_unlock_irq(&pdrvdata_lock); port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE); + spin_lock_irq(&pdrvdata_lock); if (IS_ERR(port->cons.hvc)) { ret = PTR_ERR(port->cons.hvc); dev_err(port->dev, "error %d allocating hvc for port\n", ret); port->cons.hvc = NULL; + port->cons.vtermno = pdrvdata.next_vtermno--; + spin_unlock_irq(&pdrvdata_lock); return ret; } - spin_lock_irq(&pdrvdata_lock); - pdrvdata.next_vtermno++; list_add_tail(&port->cons.list, &pdrvdata.consoles); spin_unlock_irq(&pdrvdata_lock); port->guest_connected = true;
Miche Baker-Harvey
2011-Nov-08 21:45 UTC
[PATCH v3 2/3] hvc_init(): Enforce one-time initialization.
hvc_init() must only be called once, and no thread should continue with hvc_alloc() until after initialization is complete. The original code does not enforce either of these requirements. A new mutex limits entry to hvc_init() to a single thread, and blocks all later comers until it has completed. This patch fixes multiple crash symptoms. Signed-off-by: Miche Baker-Harvey <miche at google.com> --- drivers/tty/hvc/hvc_console.c | 13 +++++++++++-- 1 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index b6b2d18..09a6159 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -29,8 +29,9 @@ #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/list.h> -#include <linux/module.h> #include <linux/major.h> +#include <linux/module.h> +#include <linux/mutex.h> #include <linux/sysrq.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -84,6 +85,10 @@ static LIST_HEAD(hvc_structs); * list traversal. */ static DEFINE_SPINLOCK(hvc_structs_lock); +/* + * only one task does allocation at a time. + */ +static DEFINE_MUTEX(hvc_ports_mutex); /* * This value is used to assign a tty->index value to a hvc_struct based @@ -825,11 +830,15 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, int i; /* We wait until a driver actually comes along */ + mutex_lock(&hvc_ports_mutex); if (!hvc_driver) { int err = hvc_init(); - if (err) + if (err) { + mutex_unlock(&hvc_ports_mutex); return ERR_PTR(err); + } } + mutex_unlock(&hvc_ports_mutex); hp = kzalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size, GFP_KERNEL);
Miche Baker-Harvey
2011-Nov-08 21:45 UTC
[PATCH v3 3/3] Use separate struct console structure for each hvc_console.
It is possible to make any virtio_console port be a console by sending VIRITO_CONSOLE_CONSOLE_PORT. But hvc_alloc was using a single struct console hvc_console, which contains both an index and flags which are per-port. This adds a separate struct console for each virtio_console that is CONSOLE_PORT. Signed-off-by: Miche Baker-Harvey <miche at google.com> --- drivers/tty/hvc/hvc_console.c | 20 ++++++++++++++++++++ drivers/tty/hvc/hvc_console.h | 1 + 2 files changed, 21 insertions(+), 0 deletions(-) diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 09a6159..24a84d6 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -247,6 +247,7 @@ static void destroy_hvc_struct(struct kref *kref) spin_unlock(&hvc_structs_lock); + kfree(hp->hvc_console); kfree(hp); } @@ -827,6 +828,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, int outbuf_size) { struct hvc_struct *hp; + struct console *cp; int i; /* We wait until a driver actually comes along */ @@ -854,6 +856,17 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, kref_init(&hp->kref); INIT_WORK(&hp->tty_resize, hvc_set_winsz); + /* + * Make each console its own struct console. + */ + cp = kmemdup(&hvc_console, sizeof(*cp), GFP_KERNEL); + if (!cp) { + kfree(hp); + return ERR_PTR(-ENOMEM); + } + + hp->hvc_console = cp; + spin_lock_init(&hp->lock); spin_lock(&hvc_structs_lock); @@ -872,8 +885,13 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data, hp->index = i; + cp->index = i; + vtermnos[i] = vtermno; + cons_ops[i] = ops; + list_add_tail(&(hp->next), &hvc_structs); spin_unlock(&hvc_structs_lock); + register_console(cp); return hp; } @@ -884,6 +902,8 @@ int hvc_remove(struct hvc_struct *hp) unsigned long flags; struct tty_struct *tty; + BUG_ON(!hp->hvc_console); + unregister_console(hp->hvc_console); spin_lock_irqsave(&hp->lock, flags); tty = tty_kref_get(hp->tty); diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h index c335a14..2d20ab7 100644 --- a/drivers/tty/hvc/hvc_console.h +++ b/drivers/tty/hvc/hvc_console.h @@ -58,6 +58,7 @@ struct hvc_struct { const struct hv_ops *ops; int irq_requested; int data; + struct console *hvc_console; struct winsize ws; struct work_struct tty_resize; struct list_head next;
Reasonably Related Threads
- [PATCH RFC v2 0/3] Support multiple VirtioConsoles.
- [PATCH RFC v2 0/3] Support multiple VirtioConsoles.
- [PATCH RFC v3 0/3] Support multiple VirtioConsoles.
- [PATCH RFC v3 0/3] Support multiple VirtioConsoles.
- [PATCH RFC v2 0/3] Support multiple VirtioConsoles.