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

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



Patches 1/5 and 3/5 did not apply. I have applied patch 2/5 however.

 -- Keir

On 11/06/2009 18:07, "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 = 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 @@
>  #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®.