Stefano Stabellini
2009-Jun-11 15:07 UTC
[Xen-devel] [PATCH] 1 of 5: secondary consoles in minos
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@eu.citrix.com> --- 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@lists.xensource.com http://lists.xensource.com/xen-devel
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@eu.citrix.com> 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@eu.citrix.com> > > --- > > 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@lists.xensource.com > http://lists.xensource.com/xen-devel >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Stefano Stabellini
2009-Jun-15 09:49 UTC
Re: [Xen-devel] [PATCH] 1 of 5: secondary consoles in minos
Dulloor wrote:> 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.Good point.> Also, is it too difficult to create a consfront_dev for the first > console and get rid of those !dev checks.No, it is not difficult, I actually wrote it that way the first time. However I would need to keep the checks anyway because the first console is used even before init_console is called. Therefore I decided to avoid calling init_console for the first console and use the !dev checks for it. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2009-Jun-16 10:21 UTC
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@eu.citrix.com> 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@eu.citrix.com> > > --- > > 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@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2009-Jun-16 10:27 UTC
Re: [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@eu.citrix.com> 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@eu.citrix.com> > 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@eu.citrix.com> >> >> --- >> >> 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@lists.xensource.com >> http://lists.xensource.com/xen-devel > > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel