xen: make hvc_xen console work for dom0.
authorJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Thu, 2 Sep 2010 15:17:06 +0000 (16:17 +0100)
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>
Fri, 22 Oct 2010 20:26:01 +0000 (21:26 +0100)
Use the console hypercalls for dom0 console.

[ Impact: Add Xen dom0 console ]
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
drivers/char/hvc_xen.c
drivers/xen/events.c
include/xen/events.h

index 60446f8..1f7e13a 100644 (file)
@@ -78,7 +78,7 @@ static int __write_console(const char *data, int len)
        return sent;
 }
 
-static int write_console(uint32_t vtermno, const char *data, int len)
+static int domU_write_console(uint32_t vtermno, const char *data, int len)
 {
        int ret = len;
 
@@ -101,7 +101,7 @@ static int write_console(uint32_t vtermno, const char *data, int len)
        return ret;
 }
 
-static int read_console(uint32_t vtermno, char *buf, int len)
+static int domU_read_console(uint32_t vtermno, char *buf, int len)
 {
        struct xencons_interface *intf = xencons_interface();
        XENCONS_RING_IDX cons, prod;
@@ -122,28 +122,62 @@ static int read_console(uint32_t vtermno, char *buf, int len)
        return recv;
 }
 
-static const struct hv_ops hvc_ops = {
-       .get_chars = read_console,
-       .put_chars = write_console,
+static struct hv_ops domU_hvc_ops = {
+       .get_chars = domU_read_console,
+       .put_chars = domU_write_console,
        .notifier_add = notifier_add_irq,
        .notifier_del = notifier_del_irq,
        .notifier_hangup = notifier_hangup_irq,
 };
 
-static int __init xen_init(void)
+static int dom0_read_console(uint32_t vtermno, char *buf, int len)
+{
+       return HYPERVISOR_console_io(CONSOLEIO_read, len, buf);
+}
+
+/*
+ * Either for a dom0 to write to the system console, or a domU with a
+ * debug version of Xen
+ */
+static int dom0_write_console(uint32_t vtermno, const char *str, int len)
+{
+       int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
+       if (rc < 0)
+               return 0;
+
+       return len;
+}
+
+static struct hv_ops dom0_hvc_ops = {
+       .get_chars = dom0_read_console,
+       .put_chars = dom0_write_console,
+       .notifier_add = notifier_add_irq,
+       .notifier_del = notifier_del_irq,
+       .notifier_hangup = notifier_hangup_irq,
+};
+
+static int __init xen_hvc_init(void)
 {
        struct hvc_struct *hp;
+       struct hv_ops *ops;
 
-       if (!xen_pv_domain() ||
-           xen_initial_domain() ||
-           !xen_start_info->console.domU.evtchn)
+       if (!xen_pv_domain())
                return -ENODEV;
 
-       xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
+       if (xen_initial_domain()) {
+               ops = &dom0_hvc_ops;
+               xencons_irq = bind_virq_to_irq(VIRQ_CONSOLE, 0);
+       } else {
+               if (!xen_start_info->console.domU.evtchn)
+                       return -ENODEV;
+
+               ops = &domU_hvc_ops;
+               xencons_irq = bind_evtchn_to_irq(xen_start_info->console.domU.evtchn);
+       }
        if (xencons_irq < 0)
                xencons_irq = 0; /* NO_IRQ */
 
-       hp = hvc_alloc(HVC_COOKIE, xencons_irq, &hvc_ops, 256);
+       hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
        if (IS_ERR(hp))
                return PTR_ERR(hp);
 
@@ -160,7 +194,7 @@ void xen_console_resume(void)
                rebind_evtchn_irq(xen_start_info->console.domU.evtchn, xencons_irq);
 }
 
-static void __exit xen_fini(void)
+static void __exit xen_hvc_fini(void)
 {
        if (hvc)
                hvc_remove(hvc);
@@ -168,29 +202,24 @@ static void __exit xen_fini(void)
 
 static int xen_cons_init(void)
 {
+       struct hv_ops *ops;
+
        if (!xen_pv_domain())
                return 0;
 
-       hvc_instantiate(HVC_COOKIE, 0, &hvc_ops);
+       if (xen_initial_domain())
+               ops = &dom0_hvc_ops;
+       else
+               ops = &domU_hvc_ops;
+
+       hvc_instantiate(HVC_COOKIE, 0, ops);
        return 0;
 }
 
-module_init(xen_init);
-module_exit(xen_fini);
+module_init(xen_hvc_init);
+module_exit(xen_hvc_fini);
 console_initcall(xen_cons_init);
 
-static void raw_console_write(const char *str, int len)
-{
-       while(len > 0) {
-               int rc = HYPERVISOR_console_io(CONSOLEIO_write, len, (char *)str);
-               if (rc <= 0)
-                       break;
-
-               str += rc;
-               len -= rc;
-       }
-}
-
 #ifdef CONFIG_EARLY_PRINTK
 static void xenboot_write_console(struct console *console, const char *string,
                                  unsigned len)
@@ -198,19 +227,22 @@ static void xenboot_write_console(struct console *console, const char *string,
        unsigned int linelen, off = 0;
        const char *pos;
 
-       raw_console_write(string, len);
+       dom0_write_console(0, string, len);
+
+       if (xen_initial_domain())
+               return;
 
-       write_console(0, "(early) ", 8);
+       domU_write_console(0, "(early) ", 8);
        while (off < len && NULL != (pos = strchr(string+off, '\n'))) {
                linelen = pos-string+off;
                if (off + linelen > len)
                        break;
-               write_console(0, string+off, linelen);
-               write_console(0, "\r\n", 2);
+               domU_write_console(0, string+off, linelen);
+               domU_write_console(0, "\r\n", 2);
                off += linelen + 1;
        }
        if (off < len)
-               write_console(0, string+off, len-off);
+               domU_write_console(0, string+off, len-off);
 }
 
 struct console xenboot_console = {
@@ -222,7 +254,7 @@ struct console xenboot_console = {
 
 void xen_raw_console_write(const char *str)
 {
-       raw_console_write(str, strlen(str));
+       dom0_write_console(0, str, strlen(str));
 }
 
 void xen_raw_printk(const char *fmt, ...)
index a7d9555..93e98ff 100644 (file)
@@ -839,7 +839,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 }
 
 
-static int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
+int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 {
        struct evtchn_bind_virq bind_virq;
        int evtchn, irq;
index 8fa27dc..646dd17 100644 (file)
@@ -12,6 +12,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
                              irq_handler_t handler,
                              unsigned long irqflags, const char *devname,
                              void *dev_id);
+int bind_virq_to_irq(unsigned int virq, unsigned int cpu);
 int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
                            irq_handler_t handler,
                            unsigned long irqflags, const char *devname,