[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>, xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • From: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>
  • Date: Tue, 16 Jun 2009 11:27:11 +0100
  • Cc:
  • Delivery-date: Tue, 16 Jun 2009 03:27:49 -0700
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>
  • Thread-index: Acnqpv2aqEL7OG2QSb+FgSLSZVbNjADxUngEAAAupHE=
  • Thread-topic: [Xen-devel] [PATCH] 1 of 5: secondary consoles in minos

Actually I have applied 3/5 okay after all. Just patch 1/5 needs refreshing
(and of course the qemu patches are handled by Ian Jackson).

 -- Keir

On 16/06/2009 11:21, "Keir Fraser" <keir.fraser@xxxxxxxxxxxxx> wrote:

> 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



_______________________________________________
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®.