[PATCH] kvm: nofity thost when guest is panicked

From: Wen Congyang
Date: Mon Apr 16 2012 - 23:01:01 EST


Signed-off-by: Wen Congyang <wency@xxxxxxxxxxxxxx>
---
drivers/char/virtio_console.c | 49 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index ddf86b6..ecccd30 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -225,8 +225,14 @@ struct port {

/* We should allow only one process to open a port */
bool guest_connected;
+
+ /* We use this port to tell the host that the guest is panicked */
+ bool panicked_port;
+ char *panicked_buf;
};

+static struct port *panicked_port;
+
/* This is the very early arch-specified put chars function. */
static int (*early_put_chars)(u32, const char *, int);

@@ -806,6 +812,15 @@ static int port_fops_open(struct inode *inode, struct file *filp)
goto out;
}

+ /*
+ * Don't allow opening of panicked port devices -- that's reserved
+ * for kernel space
+ */
+ if (port->panicked_port) {
+ ret = -ENXIO;
+ goto out;
+ }
+
/* Allow only one process to open a particular port at a time */
spin_lock_irq(&port->inbuf_lock);
if (port->guest_connected) {
@@ -1126,6 +1141,20 @@ static void send_sigio_to_port(struct port *port)
kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
}

+static int
+kvm_pv_panic_notify(struct notifier_block *nb, unsigned long code, void *unused)
+{
+ send_control_msg(panicked_port, VIRTIO_CONSOLE_PORT_OPEN, 1);
+ memcpy(panicked_port->panicked_buf, "Kernel panicked\n", 16);
+ send_buf(panicked_port, panicked_port->panicked_buf, 16, true);
+ send_control_msg(panicked_port, VIRTIO_CONSOLE_CONSOLE_PORT, 0);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block kvm_pv_panic_nb = {
+ .notifier_call = kvm_pv_panic_notify,
+};
+
static int add_port(struct ports_device *portdev, u32 id)
{
char debugfs_name[16];
@@ -1262,6 +1291,10 @@ static void remove_port(struct kref *kref)

debugfs_remove(port->debugfs_file);

+ if (port->panicked_port)
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &kvm_pv_panic_nb);
+
kfree(port);
}

@@ -1433,6 +1466,22 @@ static void handle_control_message(struct ports_device *portdev,
name_size - 1);
port->name[name_size - 1] = 0;

+ if (!panicked_port && !strcmp(port->name, "status")) {
+ port->panicked_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!port->panicked_buf) {
+ dev_warn(port->dev,
+ "Not enough space to store panicked"
+ " message");
+ goto skip;
+ }
+ send_sigio_to_port(port);
+ port->panicked_port = true;
+ panicked_port = port;
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &kvm_pv_panic_nb);
+ }
+
+skip:
/*
* Since we only have one sysfs attribute, 'name',
* create it only if we have a name for the port.
--
1.7.1


--------------020707050400000107060308--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/