[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] minios: support secondary guest consoles.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1245219738 -3600 # Node ID 11d8ca329b5419ff48acbde150569adf27bbf474 # Parent aaab04808ee7f7504abc0c6a4fe5daf14968f184 minios: support secondary guest consoles. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- extras/mini-os/console/console.c | 16 +- extras/mini-os/console/xencons_ring.c | 261 +++++++++++++++++++++++++++++----- extras/mini-os/include/console.h | 46 ++++- extras/mini-os/include/lib.h | 4 extras/mini-os/kernel.c | 2 extras/mini-os/lib/sys.c | 22 ++ stubdom/grub/mini-os.c | 4 7 files changed, 294 insertions(+), 61 deletions(-) diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/console/console.c --- a/extras/mini-os/console/console.c Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/console/console.c Wed Jun 17 07:22:18 2009 +0100 @@ -76,11 +76,11 @@ void xencons_tx(void) #endif -void console_print(char *data, int length) +void console_print(struct consfront_dev *dev, char *data, int length) { char *curr_char, saved_char; int part_len; - int (*ring_send_fn)(const char *data, unsigned length); + int (*ring_send_fn)(struct consfront_dev *dev, const char *data, unsigned length); if(!console_initialised) ring_send_fn = xencons_ring_send_no_notify; @@ -94,17 +94,17 @@ void console_print(char *data, int lengt saved_char = *(curr_char+1); *(curr_char+1) = '\r'; part_len = curr_char - data + 2; - ring_send_fn(data, part_len); + ring_send_fn(dev, data, part_len); *(curr_char+1) = saved_char; data = curr_char+1; length -= part_len - 1; } } - ring_send_fn(data, length); + ring_send_fn(dev, data, length); if(data[length-1] == '\n') - ring_send_fn("\r", 1); + ring_send_fn(dev, "\r", 1); } void print(int direct, const char *fmt, va_list args) @@ -123,7 +123,7 @@ void print(int direct, const char *fmt, #endif (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(buf), buf); - console_print(buf, strlen(buf)); + console_print(NULL, buf, strlen(buf)); } } @@ -151,7 +151,7 @@ void init_console(void) printk("done.\n"); } -void fini_console(void) +void fini_console(struct consfront_dev *dev) { - /* Destruct the console and get the parameters of the restarted one */ + if (dev) free_consfront(dev); } diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/console/xencons_ring.c --- a/extras/mini-os/console/xencons_ring.c Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/console/xencons_ring.c Wed Jun 17 07:22:18 2009 +0100 @@ -7,25 +7,38 @@ #include <lib.h> #include <xenbus.h> #include <xen/io/console.h> +#include <xen/io/protocols.h> +#include <xen/io/ring.h> +#include <xmalloc.h> +#include <gnttab.h> DECLARE_WAIT_QUEUE_HEAD(console_queue); +static inline void notify_daemon(struct consfront_dev *dev) +{ + /* Use evtchn: this is called early, before irq is set up. */ + if (!dev) + notify_remote_via_evtchn(start_info.console.domU.evtchn); + else + notify_remote_via_evtchn(dev->evtchn); +} + static inline struct xencons_interface *xencons_interface(void) { return mfn_to_virt(start_info.console.domU.mfn); -} - -static inline void notify_daemon(void) -{ - /* Use evtchn: this is called early, before irq is set up. */ - notify_remote_via_evtchn(start_info.console.domU.evtchn); -} - -int xencons_ring_send_no_notify(const char *data, unsigned len) +} + +int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len) { int sent = 0; - struct xencons_interface *intf = xencons_interface(); - XENCONS_RING_IDX cons, prod; + struct xencons_interface *intf; + XENCONS_RING_IDX cons, prod; + + if (!dev) + intf = xencons_interface(); + else + intf = dev->ring; + cons = intf->out_cons; prod = intf->out_prod; mb(); @@ -40,20 +53,27 @@ int xencons_ring_send_no_notify(const ch return sent; } -int xencons_ring_send(const char *data, unsigned len) +int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len) { int sent; - sent = xencons_ring_send_no_notify(data, len); - notify_daemon(); - - return sent; + + sent = xencons_ring_send_no_notify(dev, data, len); + notify_daemon(dev); + + return sent; } -static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *ign) -{ -#ifdef HAVE_LIBC +static void handle_input(evtchn_port_t port, struct pt_regs *regs, void *data) +{ +#ifdef HAVE_LIBC + struct consfront_dev *dev = (struct consfront_dev *) data; + int fd = dev ? dev->fd : -1; + + if (fd != -1) + files[fd].read = 1; + wake_up(&console_queue); #else struct xencons_interface *intf = xencons_interface(); @@ -72,17 +92,22 @@ static void handle_input(evtchn_port_t p mb(); intf->in_cons = cons; - notify_daemon(); + notify_daemon(dev); xencons_tx(); #endif } #ifdef HAVE_LIBC -int xencons_ring_avail(void) -{ - struct xencons_interface *intf = xencons_interface(); - XENCONS_RING_IDX cons, prod; +int xencons_ring_avail(struct consfront_dev *dev) +{ + struct xencons_interface *intf; + XENCONS_RING_IDX cons, prod; + + if (!dev) + intf = xencons_interface(); + else + intf = dev->ring; cons = intf->in_cons; prod = intf->in_prod; @@ -92,11 +117,16 @@ int xencons_ring_avail(void) return prod - cons; } -int xencons_ring_recv(char *data, unsigned len) -{ - struct xencons_interface *intf = xencons_interface(); +int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len) +{ + struct xencons_interface *intf; XENCONS_RING_IDX cons, prod; unsigned filled = 0; + + if (!dev) + intf = xencons_interface(); + else + intf = dev->ring; cons = intf->in_cons; prod = intf->in_prod; @@ -111,31 +141,190 @@ int xencons_ring_recv(char *data, unsign mb(); intf->in_cons = cons + filled; - notify_daemon(); + notify_daemon(dev); return filled; } #endif -int xencons_ring_init(void) +struct consfront_dev *xencons_ring_init(void) { int err; + struct consfront_dev *dev; if (!start_info.console.domU.evtchn) return 0; - err = bind_evtchn(start_info.console.domU.evtchn, handle_input, - NULL); + dev = malloc(sizeof(struct consfront_dev)); + memset(dev, 0, sizeof(struct consfront_dev)); + dev->nodename = "device/console"; + dev->dom = 0; + dev->backend = 0; + dev->ring_ref = 0; + +#ifdef HAVE_LIBC + dev->fd = -1; +#endif + dev->evtchn = start_info.console.domU.evtchn; + dev->ring = (struct xencons_interface *) mfn_to_virt(start_info.console.domU.mfn); + + err = bind_evtchn(dev->evtchn, handle_input, dev); if (err <= 0) { printk("XEN console request chn bind failed %i\n", err); - return err; + free(dev); + return NULL; } - unmask_evtchn(start_info.console.domU.evtchn); + unmask_evtchn(dev->evtchn); /* In case we have in-flight data after save/restore... */ - notify_daemon(); - - return 0; + notify_daemon(dev); + + return dev; +} + +void free_consfront(struct consfront_dev *dev) +{ + mask_evtchn(dev->evtchn); + + free(dev->backend); + + gnttab_end_access(dev->ring_ref); + free_page(dev->ring); + + unbind_evtchn(dev->evtchn); + + free(dev->nodename); + free(dev); +} + +struct consfront_dev *init_consfront(char *_nodename) +{ + xenbus_transaction_t xbt; + char* err; + char* message=NULL; + int retry=0; + char* msg; + char nodename[256]; + char path[256]; + static int consfrontends = 1; + struct consfront_dev *dev; + int res; + + if (!_nodename) + snprintf(nodename, sizeof(nodename), "device/console/%d", consfrontends); + else + strncpy(nodename, _nodename, sizeof(nodename)); + + printk("******************* CONSFRONT for %s **********\n\n\n", nodename); + + consfrontends++; + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + dev->nodename = strdup(nodename); +#ifdef HAVE_LIBC + dev->fd = -1; +#endif + + snprintf(path, sizeof(path), "%s/backend-id", nodename); + if ((res = xenbus_read_integer(path)) < 0) + return NULL; + else + dev->dom = res; + evtchn_alloc_unbound(dev->dom, handle_input, dev, &dev->evtchn); + + dev->ring = (struct xencons_interface *) alloc_page(); + memset(dev->ring, 0, PAGE_SIZE); + dev->ring_ref = gnttab_grant_access(dev->dom, virt_to_mfn(dev->ring), 0); + + dev->events = NULL; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + printk("starting transaction\n"); + } + + err = xenbus_printf(xbt, nodename, "ring-ref","%u", + dev->ring_ref); + if (err) { + message = "writing ring-ref"; + goto abort_transaction; + } + err = xenbus_printf(xbt, nodename, + "port", "%u", dev->evtchn); + if (err) { + message = "writing event-channel"; + goto abort_transaction; + } + err = xenbus_printf(xbt, nodename, + "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); + if (err) { + message = "writing protocol"; + goto abort_transaction; + } + + err = xenbus_printf(xbt, nodename, "type", "%s", "ioemu"); + if (err) { + message = "writing type"; + goto abort_transaction; + } + + snprintf(path, sizeof(path), "%s/state", nodename); + err = xenbus_switch_state(xbt, path, XenbusStateConnected); + if (err) { + message = "switching state"; + goto abort_transaction; + } + + + err = xenbus_transaction_end(xbt, 0, &retry); + if (retry) { + goto again; + printk("completing transaction\n"); + } + + goto done; + +abort_transaction: + xenbus_transaction_end(xbt, 1, &retry); + goto error; + +done: + + snprintf(path, sizeof(path), "%s/backend", nodename); + msg = xenbus_read(XBT_NIL, path, &dev->backend); + if (msg) { + printk("Error %s when reading the backend path %s\n", msg, path); + goto error; + } + + printk("backend at %s\n", dev->backend); + + { + XenbusState state; + char path[strlen(dev->backend) + 1 + 19 + 1]; + snprintf(path, sizeof(path), "%s/state", dev->backend); + + xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); + msg = NULL; + state = xenbus_read_integer(path); + while (msg == NULL && state < XenbusStateConnected) + msg = xenbus_wait_for_state_change(path, &state, &dev->events); + if (msg != NULL || state != XenbusStateConnected) { + printk("backend not available, state=%d\n", state); + xenbus_unwatch_path(XBT_NIL, path); + goto error; + } + } + unmask_evtchn(dev->evtchn); + + printk("**************************\n"); + + return dev; + +error: + free_consfront(dev); + return NULL; } void xencons_resume(void) diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/include/console.h --- a/extras/mini-os/include/console.h Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/include/console.h Wed Jun 17 07:22:18 2009 +0100 @@ -36,9 +36,32 @@ #ifndef _LIB_CONSOLE_H_ #define _LIB_CONSOLE_H_ -#include<mini-os/os.h> -#include<mini-os/traps.h> -#include<stdarg.h> +#include <mini-os/os.h> +#include <mini-os/traps.h> +#include <mini-os/types.h> +#include <xen/grant_table.h> +#include <xenbus.h> +#include <xen/io/console.h> +#include <stdarg.h> + +struct consfront_dev { + domid_t dom; + + struct xencons_interface *ring; + grant_ref_t ring_ref; + evtchn_port_t evtchn; + + char *nodename; + char *backend; + + xenbus_event_queue events; + +#ifdef HAVE_LIBC + int fd; +#endif +}; + + void print(int direct, const char *fmt, va_list args); void printk(const char *fmt, ...); @@ -50,16 +73,17 @@ void xencons_tx(void); void xencons_tx(void); void init_console(void); -void console_print(char *data, int length); -void fini_console(void); +void console_print(struct consfront_dev *dev, char *data, int length); +void fini_console(struct consfront_dev *dev); /* Low level functions defined in xencons_ring.c */ extern struct wait_queue_head console_queue; -int xencons_ring_init(void); -int xencons_ring_send(const char *data, unsigned len); -int xencons_ring_send_no_notify(const char *data, unsigned len); -int xencons_ring_avail(void); -int xencons_ring_recv(char *data, unsigned len); - +struct consfront_dev *xencons_ring_init(void); +struct consfront_dev *init_consfront(char *_nodename); +int xencons_ring_send(struct consfront_dev *dev, const char *data, unsigned len); +int xencons_ring_send_no_notify(struct consfront_dev *dev, const char *data, unsigned len); +int xencons_ring_avail(struct consfront_dev *dev); +int xencons_ring_recv(struct consfront_dev *dev, char *data, unsigned len); +void free_consfront(struct consfront_dev *dev); #endif /* _LIB_CONSOLE_H_ */ diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/include/lib.h --- a/extras/mini-os/include/lib.h Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/include/lib.h Wed Jun 17 07:22:18 2009 +0100 @@ -101,6 +101,7 @@ char *strdup(const char *s); char *strdup(const char *s); #endif #include <mini-os/console.h> +int openpty(void); #define RAND_MIX 2654435769U @@ -183,6 +184,9 @@ extern struct file { struct { struct fbfront_dev *dev; } fb; + struct { + struct consfront_dev *dev; + } cons; struct { /* To each xenbus FD is associated a queue of watch events for this * FD. */ diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/kernel.c --- a/extras/mini-os/kernel.c Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/kernel.c Wed Jun 17 07:22:18 2009 +0100 @@ -562,7 +562,7 @@ void stop_kernel(void) fini_gnttab(); /* Reset the console driver. */ - fini_console(); + fini_console(NULL); /* TODO: record new ring mfn & event in start_info */ /* Reset XenBus */ diff -r aaab04808ee7 -r 11d8ca329b54 extras/mini-os/lib/sys.c --- a/extras/mini-os/lib/sys.c Wed Jun 17 07:21:03 2009 +0100 +++ b/extras/mini-os/lib/sys.c Wed Jun 17 07:22:18 2009 +0100 @@ -165,6 +165,18 @@ int mkdir(const char *pathname, mode_t m return -1; } return 0; +} + +int openpty(void) +{ + struct consfront_dev *dev; + + dev = init_consfront(NULL); + dev->fd = alloc_fd(FTYPE_CONSOLE); + files[dev->fd].cons.dev = dev; + + printk("fd(%d) = openpty\n", dev->fd); + return(dev->fd); } int open(const char *pathname, int flags, ...) @@ -219,7 +231,7 @@ int read(int fd, void *buf, size_t nbyte DEFINE_WAIT(w); while(1) { add_waiter(w, console_queue); - ret = xencons_ring_recv(buf, nbytes); + ret = xencons_ring_recv(files[fd].cons.dev, buf, nbytes); if (ret) break; schedule(); @@ -286,7 +298,7 @@ int write(int fd, const void *buf, size_ { switch (files[fd].type) { case FTYPE_CONSOLE: - console_print((char *)buf, nbytes); + console_print(files[fd].cons.dev, (char *)buf, nbytes); return nbytes; case FTYPE_FILE: { ssize_t ret; @@ -416,6 +428,10 @@ int close(int fd) shutdown_fbfront(files[fd].fb.dev); files[fd].type = FTYPE_NONE; return 0; + case FTYPE_CONSOLE: + fini_console(files[fd].cons.dev); + files[fd].type = FTYPE_NONE; + return 0; case FTYPE_NONE: break; } @@ -735,7 +751,7 @@ static int select_poll(int nfds, fd_set break; case FTYPE_CONSOLE: if (FD_ISSET(i, readfds)) { - if (xencons_ring_avail()) + if (xencons_ring_avail(files[i].cons.dev)) n++; else FD_CLR(i, readfds); diff -r aaab04808ee7 -r 11d8ca329b54 stubdom/grub/mini-os.c --- a/stubdom/grub/mini-os.c Wed Jun 17 07:21:03 2009 +0100 +++ b/stubdom/grub/mini-os.c Wed Jun 17 07:22:18 2009 +0100 @@ -329,7 +329,7 @@ serial_hw_put (int _c) serial_hw_put (int _c) { char c = _c; - console_print(&c, 1); + console_print(NULL, &c, 1); } int @@ -337,7 +337,7 @@ serial_hw_fetch (void) { char key; - if (!xencons_ring_avail()) + if (!xencons_ring_avail(NULL)) return -1; read(STDIN_FILENO, &key, 1); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |