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

[Xen-changelog] [xen-unstable] minios: support secondary guest consoles.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1245219738 -3600
# Node ID 11d8ca329b5419ff48acbde150569adf27bbf474
# Parent  aaab04808ee7f7504abc0c6a4fe5daf14968f184
minios: support secondary guest consoles.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 extras/mini-os/console/console.c      |   16 +-
 extras/mini-os/console/xencons_ring.c |  261 +++++++++++++++++++++++++++++-----
 extras/mini-os/include/console.h      |   46 ++++-
 extras/mini-os/include/lib.h          |    4 
 extras/mini-os/kernel.c               |    2 
 extras/mini-os/lib/sys.c              |   22 ++
 stubdom/grub/mini-os.c                |    4 
 7 files changed, 294 insertions(+), 61 deletions(-)

diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/console/console.c
--- a/extras/mini-os/console/console.c  Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/console/console.c  Wed Jun 17 07:22:18 2009 +0100
@@ -76,11 +76,11 @@ void xencons_tx(void)
 #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 @@ void console_print(char *data, int lengt
             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 = curr_char+1;
             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 @@ void print(int direct, const char *fmt, 
 #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 @@ void init_console(void)
     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 aaab04808ee7 -r 11d8ca329b54 extras/mini-os/console/xencons_ring.c
--- a/extras/mini-os/console/xencons_ring.c     Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/console/xencons_ring.c     Wed Jun 17 07:22:18 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();
-       XENCONS_RING_IDX cons, prod;
+       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 @@ int xencons_ring_send_no_notify(const ch
     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)
-{
-#ifdef HAVE_LIBC
+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 @@ static void handle_input(evtchn_port_t p
        mb();
        intf->in_cons = cons;
 
-       notify_daemon();
+       notify_daemon(dev);
 
        xencons_tx();
 #endif
 }
 
 #ifdef HAVE_LIBC
-int xencons_ring_avail(void)
-{
-       struct xencons_interface *intf = xencons_interface();
-       XENCONS_RING_IDX cons, prod;
+int xencons_ring_avail(struct consfront_dev *dev)
+{
+       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 @@ int xencons_ring_avail(void)
         return prod - cons;
 }
 
-int xencons_ring_recv(char *data, unsigned len)
-{
-       struct xencons_interface *intf = xencons_interface();
+int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len)
+{
+       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,190 @@ int xencons_ring_recv(char *data, unsign
        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;
+                free(dev);
+               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();
-
-       return 0;
+       notify_daemon(dev);
+
+       return dev;
+}
+
+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);
+
+    consfrontends++;
+    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 aaab04808ee7 -r 11d8ca329b54 extras/mini-os/include/console.h
--- a/extras/mini-os/include/console.h  Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/include/console.h  Wed Jun 17 07:22:18 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 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);
+void free_consfront(struct consfront_dev *dev);
 
 #endif /* _LIB_CONSOLE_H_ */
diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/include/lib.h
--- a/extras/mini-os/include/lib.h      Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/include/lib.h      Wed Jun 17 07:22:18 2009 +0100
@@ -101,6 +101,7 @@ char  *strdup(const char *s);
 char  *strdup(const char *s);
 #endif
 #include <mini-os/console.h>
+int openpty(void);
 
 #define RAND_MIX 2654435769U
 
@@ -183,6 +184,9 @@ extern struct file {
        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 aaab04808ee7 -r 11d8ca329b54 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/kernel.c   Wed Jun 17 07:22:18 2009 +0100
@@ -562,7 +562,7 @@ void stop_kernel(void)
     fini_gnttab();
 
     /* Reset the console driver. */
-    fini_console();
+    fini_console(NULL);
     /* TODO: record new ring mfn & event in start_info */
 
     /* Reset XenBus */
diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/lib/sys.c
--- a/extras/mini-os/lib/sys.c  Wed Jun 17 07:21:03 2009 +0100
+++ b/extras/mini-os/lib/sys.c  Wed Jun 17 07:22:18 2009 +0100
@@ -165,6 +165,18 @@ int mkdir(const char *pathname, mode_t m
         return -1;
     }
     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, ...)
@@ -219,7 +231,7 @@ int read(int fd, void *buf, size_t nbyte
             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 @@ int write(int fd, const void *buf, size_
 {
     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;
@@ -416,6 +428,10 @@ int close(int fd)
             shutdown_fbfront(files[fd].fb.dev);
             files[fd].type = FTYPE_NONE;
             return 0;
+        case FTYPE_CONSOLE:
+            fini_console(files[fd].cons.dev);
+            files[fd].type = FTYPE_NONE;
+            return 0;
        case FTYPE_NONE:
            break;
     }
@@ -735,7 +751,7 @@ static int select_poll(int nfds, fd_set 
            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 aaab04808ee7 -r 11d8ca329b54 stubdom/grub/mini-os.c
--- a/stubdom/grub/mini-os.c    Wed Jun 17 07:21:03 2009 +0100
+++ b/stubdom/grub/mini-os.c    Wed Jun 17 07:22:18 2009 +0100
@@ -329,7 +329,7 @@ serial_hw_put (int _c)
 serial_hw_put (int _c)
 {
   char c = _c;
-  console_print(&c, 1);
+  console_print(NULL, &c, 1);
 }
 
 int
@@ -337,7 +337,7 @@ serial_hw_fetch (void)
 {
     char key;
 
-    if (!xencons_ring_avail())
+    if (!xencons_ring_avail(NULL))
         return -1;
 
     read(STDIN_FILENO, &key, 1);

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


 


Rackspace

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