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