# 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
|