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

Re: [Xen-devel] [PATCH] 1 of 5: secondary consoles in minos


  • To: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
  • From: Dulloor <dulloor@xxxxxxxxx>
  • Date: Fri, 12 Jun 2009 00:55:23 -0400
  • Cc: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • Delivery-date: Thu, 11 Jun 2009 21:56:49 -0700
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=u7Qv5dsESH/uXUXPaBJS/GiW2ibOVZhsDLijXk5jH+urqVYvR7GEr5S4w0AFX3d90H brh632DiTKjbqv0I3D0hSjO31thUK+A/FRXP4IkxorRPrHiTXlfID0GraqwMA7l5YlMc kmYjAq07uy5woQVRAte/mqq4+nrocpwdT8zdY=
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

For completeness, we should be freeing up memory(malloced for dev) in case of an error in xencons_ring_init. There could be other such instances.

Also, is it too difficult to create a consfront_dev for the first console and get rid of those !dev checks.

-dulloor

On Thu, Jun 11, 2009 at 11:07 AM, Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> wrote:
This patch implements support for more than one serial in MiniOS console
frontend.
The code to setup the first console remains a little bit different from
the rest because of the particular way the first console is provided to
a pv guests.
The new code to handle secondary consoles is much more similar to other
frontends.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

---

diff -r 112680f620bf extras/mini-os/console/console.c
--- a/extras/mini-os/console/console.c  Mon Jun 08 18:23:57 2009 +0100
+++ b/extras/mini-os/console/console.c  Thu Jun 11 15:19:43 2009 +0100
@@ -76,11 +76,11 @@
 #endif


-void console_print(char *data, int length)
+void console_print(struct consfront_dev *dev, char *data, int length)
 {
    char *curr_char, saved_char;
    int part_len;
-    int (*ring_send_fn)(const char *data, unsigned length);
+    int (*ring_send_fn)(struct consfront_dev *dev, const char *data, unsigned length);

    if(!console_initialised)
        ring_send_fn = xencons_ring_send_no_notify;
@@ -94,17 +94,17 @@
            saved_char = *(curr_char+1);
            *(curr_char+1) = '\r';
            part_len = curr_char - data + 2;
-            ring_send_fn(data, part_len);
+            ring_send_fn(dev, data, part_len);
            *(curr_char+1) = saved_char;
            data = "">             length -= part_len - 1;
        }
    }

-    ring_send_fn(data, length);
+    ring_send_fn(dev, data, length);

    if(data[length-1] == '\n')
-        ring_send_fn("\r", 1);
+        ring_send_fn(dev, "\r", 1);
 }

 void print(int direct, const char *fmt, va_list args)
@@ -123,7 +123,7 @@
 #endif
            (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf);

-        console_print(buf, strlen(buf));
+        console_print(NULL, buf, strlen(buf));
    }
 }

@@ -151,7 +151,7 @@
    printk("done.\n");
 }

-void fini_console(void)
+void fini_console(struct consfront_dev *dev)
 {
-    /* Destruct the console and get the parameters of the restarted one */
+    if (dev) free_consfront(dev);
 }
diff -r 112680f620bf extras/mini-os/console/xencons_ring.c
--- a/extras/mini-os/console/xencons_ring.c     Mon Jun 08 18:23:57 2009 +0100
+++ b/extras/mini-os/console/xencons_ring.c     Thu Jun 11 15:19:43 2009 +0100
@@ -7,25 +7,38 @@
 #include <lib.h>
 #include <xenbus.h>
 #include <xen/io/console.h>
+#include <xen/io/protocols.h>
+#include <xen/io/ring.h>
+#include <xmalloc.h>
+#include <gnttab.h>

 DECLARE_WAIT_QUEUE_HEAD(console_queue);
+
+static inline void notify_daemon(struct consfront_dev *dev)
+{
+    /* Use evtchn: this is called early, before irq is set up. */
+    if (!dev)
+        notify_remote_via_evtchn(start_info.console.domU.evtchn);
+    else
+        notify_remote_via_evtchn(dev->evtchn);
+}

 static inline struct xencons_interface *xencons_interface(void)
 {
    return mfn_to_virt(start_info.console.domU.mfn);
-}
-
-static inline void notify_daemon(void)
-{
-    /* Use evtchn: this is called early, before irq is set up. */
-    notify_remote_via_evtchn(start_info.console.domU.evtchn);
-}
-
-int xencons_ring_send_no_notify(const char *data, unsigned len)
+}
+
+int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len)
 {
    int sent = 0;
-       struct xencons_interface *intf = xencons_interface();
+       struct xencons_interface *intf;
       XENCONS_RING_IDX cons, prod;
+
+       if (!dev)
+            intf = xencons_interface();
+        else
+            intf = dev->ring;
+
       cons = intf->out_cons;
       prod = intf->out_prod;
       mb();
@@ -40,20 +53,27 @@
    return sent;
 }

-int xencons_ring_send(const char *data, unsigned len)
+int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len)
 {
    int sent;
-    sent = xencons_ring_send_no_notify(data, len);
-       notify_daemon();

-       return sent;
+    sent = xencons_ring_send_no_notify(dev, data, len);
+    notify_daemon(dev);
+
+    return sent;
 }



-static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign)
+static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *data)
 {
 #ifdef HAVE_LIBC
+       struct consfront_dev *dev = (struct consfront_dev *) data;
+        int fd = dev ? dev->fd : -1;
+
+        if (fd != -1)
+            files[fd].read = 1;
+
        wake_up(&console_queue);
 #else
       struct xencons_interface *intf = xencons_interface();
@@ -72,17 +92,22 @@
       mb();
       intf->in_cons = cons;

-       notify_daemon();
+       notify_daemon(dev);

       xencons_tx();
 #endif
 }

 #ifdef HAVE_LIBC
-int xencons_ring_avail(void)
+int xencons_ring_avail(struct consfront_dev *dev)
 {
-       struct xencons_interface *intf = xencons_interface();
+       struct xencons_interface *intf;
       XENCONS_RING_IDX cons, prod;
+
+        if (!dev)
+            intf = xencons_interface();
+        else
+            intf = dev->ring;

       cons = intf->in_cons;
       prod = intf->in_prod;
@@ -92,11 +117,16 @@
        return prod - cons;
 }

-int xencons_ring_recv(char *data, unsigned len)
+int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
 {
-       struct xencons_interface *intf = xencons_interface();
+       struct xencons_interface *intf;
       XENCONS_RING_IDX cons, prod;
        unsigned filled = 0;
+
+        if (!dev)
+            intf = xencons_interface();
+        else
+            intf = dev->ring;

       cons = intf->in_cons;
       prod = intf->in_prod;
@@ -111,31 +141,188 @@
       mb();
        intf->in_cons = cons + filled;

-       notify_daemon();
+       notify_daemon(dev);

        return filled;
 }
 #endif

-int xencons_ring_init(void)
+struct consfront_dev *xencons_ring_init(void)
 {
       int err;
+       struct consfront_dev *dev;

       if (!start_info.console.domU.evtchn)
               return 0;

-       err = bind_evtchn(start_info.console.domU.evtchn, handle_input,
-                         NULL);
+       dev = malloc(sizeof(struct consfront_dev));
+       memset(dev, 0, sizeof(struct consfront_dev));
+       dev->nodename = "device/console";
+       dev->dom = 0;
+       dev->backend = 0;
+       dev->ring_ref = 0;
+
+#ifdef HAVE_LIBC
+       dev->fd = -1;
+#endif
+       dev->evtchn = start_info.console.domU.evtchn;
+       dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn);
+
+       err = bind_evtchn(dev->evtchn, handle_input, dev);
       if (err <= 0) {
               printk("XEN console request chn bind failed %i\n", err);
-               return err;
+               return NULL;
       }
-        unmask_evtchn(start_info.console.domU.evtchn);
+        unmask_evtchn(dev->evtchn);

       /* In case we have in-flight data after save/restore... */
-       notify_daemon();
+       notify_daemon(dev);

-       return 0;
+       return dev;
+}
+
+static void free_consfront(struct consfront_dev *dev)
+{
+    mask_evtchn(dev->evtchn);
+
+    free(dev->backend);
+
+    gnttab_end_access(dev->ring_ref);
+    free_page(dev->ring);
+
+    unbind_evtchn(dev->evtchn);
+
+    free(dev->nodename);
+    free(dev);
+}
+
+struct consfront_dev *init_consfront(char *_nodename)
+{
+    xenbus_transaction_t xbt;
+    char* err;
+    char* message=NULL;
+    int retry=0;
+    char* msg;
+    char nodename[256];
+    char path[256];
+    static int consfrontends = 1;
+    struct consfront_dev *dev;
+    int res;
+
+    if (!_nodename)
+        snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends);
+    else
+        strncpy(nodename, _nodename, sizeof(nodename));
+
+    printk("******************* CONSFRONT for %s **********\n\n\n", nodename);
+
+    dev = malloc(sizeof(*dev));
+    memset(dev, 0, sizeof(*dev));
+    dev->nodename = strdup(nodename);
+#ifdef HAVE_LIBC
+    dev->fd = -1;
+#endif
+
+    snprintf(path, sizeof(path), "%s/backend-id", nodename);
+    if ((res = xenbus_read_integer(path)) < 0)
+        return NULL;
+    else
+        dev->dom = res;
+    evtchn_alloc_unbound(dev->dom, handle_input, dev, &dev->evtchn);
+
+    dev->ring = (struct xencons_interface *) alloc_page();
+    memset(dev->ring, 0, PAGE_SIZE);
+    dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0);
+
+    dev->events = NULL;
+
+again:
+    err = xenbus_transaction_start(&xbt);
+    if (err) {
+        printk("starting transaction\n");
+    }
+
+    err = xenbus_printf(xbt, nodename, "ring-ref","%u",
+                dev->ring_ref);
+    if (err) {
+        message = "writing ring-ref";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "port", "%u", dev->evtchn);
+    if (err) {
+        message = "writing event-channel";
+        goto abort_transaction;
+    }
+    err = xenbus_printf(xbt, nodename,
+                "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
+    if (err) {
+        message = "writing protocol";
+        goto abort_transaction;
+    }
+
+    err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu");
+    if (err) {
+        message = "writing type";
+        goto abort_transaction;
+    }
+
+    snprintf(path, sizeof(path), "%s/state", nodename);
+    err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+    if (err) {
+        message = "switching state";
+        goto abort_transaction;
+    }
+
+
+    err = xenbus_transaction_end(xbt, 0, &retry);
+    if (retry) {
+            goto again;
+        printk("completing transaction\n");
+    }
+
+    goto done;
+
+abort_transaction:
+    xenbus_transaction_end(xbt, 1, &retry);
+    goto error;
+
+done:
+
+    snprintf(path, sizeof(path), "%s/backend", nodename);
+    msg = xenbus_read(XBT_NIL, path, &dev->backend);
+    if (msg) {
+        printk("Error %s when reading the backend path %s\n", msg, path);
+        goto error;
+    }
+
+    printk("backend at %s\n", dev->backend);
+
+    {
+        XenbusState state;
+        char path[strlen(dev->backend) + 1 + 19 + 1];
+        snprintf(path, sizeof(path), "%s/state", dev->backend);
+
+       xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
+        msg = NULL;
+        state = xenbus_read_integer(path);
+        while (msg == NULL && state < XenbusStateConnected)
+            msg = xenbus_wait_for_state_change(path, &state, &dev->events);
+        if (msg != NULL || state != XenbusStateConnected) {
+            printk("backend not available, state=%d\n", state);
+            xenbus_unwatch_path(XBT_NIL, path);
+            goto error;
+        }
+    }
+    unmask_evtchn(dev->evtchn);
+
+    printk("**************************\n");
+
+    return dev;
+
+error:
+    free_consfront(dev);
+    return NULL;
 }

 void xencons_resume(void)
diff -r 112680f620bf extras/mini-os/include/console.h
--- a/extras/mini-os/include/console.h  Mon Jun 08 18:23:57 2009 +0100
+++ b/extras/mini-os/include/console.h  Thu Jun 11 15:19:43 2009 +0100
@@ -36,9 +36,32 @@
 #ifndef _LIB_CONSOLE_H_
 #define _LIB_CONSOLE_H_

-#include<mini-os/os.h>
-#include<mini-os/traps.h>
-#include<stdarg.h>
+#include <mini-os/os.h>
+#include <mini-os/traps.h>
+#include <mini-os/types.h>
+#include <xen/grant_table.h>
+#include <xenbus.h>
+#include <xen/io/console.h>
+#include <stdarg.h>
+
+struct consfront_dev {
+    domid_t dom;
+
+    struct xencons_interface *ring;
+    grant_ref_t ring_ref;
+    evtchn_port_t evtchn;
+
+    char *nodename;
+    char *backend;
+
+    xenbus_event_queue events;
+
+#ifdef HAVE_LIBC
+    int fd;
+#endif
+};
+
+

 void print(int direct, const char *fmt, va_list args);
 void printk(const char *fmt, ...);
@@ -50,16 +73,17 @@
 void xencons_tx(void);

 void init_console(void);
-void console_print(char *data, int length);
-void fini_console(void);
+void console_print(struct consfront_dev *dev, char *data, int length);
+void fini_console(struct consfront_dev *dev);

 /* Low level functions defined in xencons_ring.c */
 extern struct wait_queue_head console_queue;
-int xencons_ring_init(void);
-int xencons_ring_send(const char *data, unsigned len);
-int xencons_ring_send_no_notify(const char *data, unsigned len);
-int xencons_ring_avail(void);
-int xencons_ring_recv(char *data, unsigned len);
+struct consfront_dev *xencons_ring_init(void);
+struct consfront_dev *init_consfront(char *_nodename);
+int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len);
+int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len);
+int xencons_ring_avail(struct consfront_dev *dev);
+int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len);


 #endif /* _LIB_CONSOLE_H_ */
diff -r 112680f620bf extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Mon Jun 08 18:23:57 2009 +0100
+++ b/extras/mini-os/include/lib.h      Thu Jun 11 15:19:43 2009 +0100
@@ -101,6 +101,7 @@
 char  *strdup(const char *s);
 #endif
 #include <mini-os/console.h>
+int openpty(void);

 #define RAND_MIX 2654435769U

@@ -183,6 +184,9 @@
       struct {
           struct fbfront_dev *dev;
       } fb;
+       struct {
+           struct consfront_dev *dev;
+       } cons;
        struct {
            /* To each xenbus FD is associated a queue of watch events for this
             * FD.  */
diff -r 112680f620bf extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Mon Jun 08 18:23:57 2009 +0100
+++ b/extras/mini-os/lib/sys.c  Thu Jun 11 15:19:43 2009 +0100
@@ -167,6 +167,18 @@
    return 0;
 }

+int openpty(void)
+{
+    struct consfront_dev *dev;
+
+    dev = init_consfront(NULL);
+    dev->fd = alloc_fd(FTYPE_CONSOLE);
+    files[dev->fd].cons.dev = dev;
+
+    printk("fd(%d) = openpty\n", dev->fd);
+    return(dev->fd);
+}
+
 int open(const char *pathname, int flags, ...)
 {
    int fs_fd, fd;
@@ -219,7 +231,7 @@
            DEFINE_WAIT(w);
            while(1) {
                add_waiter(w, console_queue);
-                ret = xencons_ring_recv(buf, nbytes);
+                ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes);
                if (ret)
                    break;
                schedule();
@@ -286,7 +298,7 @@
 {
    switch (files[fd].type) {
       case FTYPE_CONSOLE:
-           console_print((char *)buf, nbytes);
+           console_print(files[fd].cons.dev, (char *)buf, nbytes);
           return nbytes;
       case FTYPE_FILE: {
           ssize_t ret;
@@ -414,6 +426,10 @@
            return 0;
       case FTYPE_FB:
            shutdown_fbfront(files[fd].fb.dev);
+            files[fd].type = FTYPE_NONE;
+            return 0;
+        case FTYPE_CONSOLE:
+            fini_console(files[fd].fb.dev);
            files[fd].type = FTYPE_NONE;
            return 0;
       case FTYPE_NONE:
@@ -735,7 +751,7 @@
           break;
       case FTYPE_CONSOLE:
           if (FD_ISSET(i, readfds)) {
-                if (xencons_ring_avail())
+                if (xencons_ring_avail(files[i].cons.dev))
                   n++;
               else
                   FD_CLR(i, readfds);
diff -r 112680f620bf stubdom/grub/mini-os.c
--- a/stubdom/grub/mini-os.c    Mon Jun 08 18:23:57 2009 +0100
+++ b/stubdom/grub/mini-os.c    Thu Jun 11 15:19:43 2009 +0100
@@ -329,7 +329,7 @@
 serial_hw_put (int _c)
 {
  char c = _c;
-  console_print(&c, 1);
+  console_print(NULL, &c, 1);
 }

 int
@@ -337,7 +337,7 @@
 {
    char key;

-    if (!xencons_ring_avail())
+    if (!xencons_ring_avail(NULL))
        return -1;

    read(STDIN_FILENO, &key, 1);

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.