aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/mini-os/fbfront.c12
-rw-r--r--extras/mini-os/include/fbfront.h3
-rw-r--r--stubdom/README75
-rw-r--r--tools/ioemu/hw/xenfb.c210
-rw-r--r--tools/ioemu/vl.c4
-rw-r--r--tools/ioemu/vl.h5
-rw-r--r--tools/ioemu/xenstore.c31
7 files changed, 311 insertions, 29 deletions
diff --git a/extras/mini-os/fbfront.c b/extras/mini-os/fbfront.c
index bbe49b92a5..4f5041ab69 100644
--- a/extras/mini-os/fbfront.c
+++ b/extras/mini-os/fbfront.c
@@ -31,13 +31,6 @@ struct kbdfront_dev {
char *nodename;
char *backend;
- char *data;
- int width;
- int height;
- int depth;
- int line_length;
- int mem_length;
-
#ifdef HAVE_LIBC
int fd;
#endif
@@ -316,7 +309,10 @@ struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int heig
for (i = 0; mapped < mem_length && i < max_pd; i++) {
unsigned long *pd = (unsigned long *) alloc_page();
for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned long); j++) {
- pd[j] = virt_to_mfn((unsigned long) data + mapped);
+ /* Trigger CoW */
+ * ((char *)data + mapped) = 0;
+ barrier();
+ pd[j] = virtual_to_mfn((unsigned long) data + mapped);
mapped += PAGE_SIZE;
}
for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
diff --git a/extras/mini-os/include/fbfront.h b/extras/mini-os/include/fbfront.h
index 502f0330a2..fa98942e76 100644
--- a/extras/mini-os/include/fbfront.h
+++ b/extras/mini-os/include/fbfront.h
@@ -14,6 +14,9 @@
#ifndef KEY_Q
#define KEY_Q 16
#endif
+#ifndef KEY_MAX
+#define KEY_MAX 0x1ff
+#endif
struct kbdfront_dev;
diff --git a/stubdom/README b/stubdom/README
index 4b9bef6b19..d4e1664b4f 100644
--- a/stubdom/README
+++ b/stubdom/README
@@ -6,39 +6,78 @@ Then make install to install the result.
Also, run make and make install in $XEN_ROOT/tools/fs-back
-To run
-======
-
-mkdir -p /exports/usr/share/qemu
-ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu
-/usr/sbin/fs-backend &
-
+General Configuration
+=====================
In your HVM config "hvmconfig",
-- use VNC, set vnclisten to "172.30.206.1" for instance. Do not use a host name
-as Mini-OS does not have a name resolver. Do not use 127.0.0.1 since then you
-will not be able to connect to it.
-
-vnc = 1
-vnclisten = "172.30.206.1"
-
- use /usr/lib/xen/bin/stubdom-dm as dm script
device_model = '/usr/lib/xen/bin/stubdom-dm'
- comment the disk statement:
+
#disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
-Create /etc/xen/stubdom-hvmconfig (where "hvmconfig" is your HVM guest domain
-name) with
+
+Create /etc/xen/stubdom-hvmconfig (where "hvmconfig" is the name of your HVM
+guest) with
kernel = "/usr/lib/xen/boot/stubdom.gz"
-vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
+vif = [ '', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
where
-- 172.30.206.1 is the IP for vnc,
+- the first vif ('') is reserved for VNC (see below)
- 'ip=10.0.1.1,mac= etc...' is the same net configuration as in the hvmconfig
script,
- and disk = is the same block configuration as in the hvmconfig script.
+
+Display Configuration
+=====================
+
+There are three posibilities
+
+* Using SDL
+
+In hvmconfig, disable vnc:
+
+vnc = 0
+
+In stubdom-hvmconfig, set a vfb:
+
+vfb = [ 'type=sdl' ]
+
+* Using a VNC server in the stub domain
+
+In hvmconfig, set vnclisten to "172.30.206.1" for instance. Do not use a host
+name as Mini-OS does not have a name resolver. Do not use 127.0.0.1 since then
+you will not be able to connect to it.
+
+vnc = 1
+vnclisten = "172.30.206.1"
+
+In stubdom-hvmconfig, fill the reserved vif with the same IP, for instance:
+
+vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
+
+* Using a VNC server in dom0
+
+In hvmconfig, disable vnc:
+
+vnc = 0
+
+In stubdom-hvmconfig, set a vfb:
+
+vfb = [ 'type=vnc' ]
+
+and any other parameter as wished.
+
+To run
+======
+
+mkdir -p /exports/usr/share/qemu
+ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu
+/usr/sbin/fs-backend &
+
+xm create hvmconfig
diff --git a/tools/ioemu/hw/xenfb.c b/tools/ioemu/hw/xenfb.c
index ea4ea14db2..e2f181126e 100644
--- a/tools/ioemu/hw/xenfb.c
+++ b/tools/ioemu/hw/xenfb.c
@@ -19,6 +19,12 @@
#include "xenfb.h"
+#ifdef CONFIG_STUBDOM
+#include <semaphore.h>
+#include <sched.h>
+#include <fbfront.h>
+#endif
+
#ifndef BTN_LEFT
#define BTN_LEFT 0x110 /* from <linux/input.h> */
#endif
@@ -1124,12 +1130,10 @@ static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
dpy_update(xenfb->ds, x, y, w, h);
}
-/* QEMU display state changed, so refresh the framebuffer copy */
-/* XXX - can we optimize this, or the next func at all ? */
+/* Periodic update of display, no need for any in our case */
static void xenfb_update(void *opaque)
{
struct xenfb *xenfb = opaque;
- xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
}
/* QEMU display state changed, so refresh the framebuffer copy */
@@ -1169,6 +1173,206 @@ static int xenfb_register_console(struct xenfb *xenfb) {
return 0;
}
+#ifdef CONFIG_STUBDOM
+static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0);
+static struct kbdfront_dev *kbd_dev;
+static char *kbd_path, *fb_path;
+
+static unsigned char linux2scancode[KEY_MAX + 1];
+
+#define WIDTH 1024
+#define HEIGHT 768
+#define DEPTH 32
+#define LINESIZE (1280 * (DEPTH / 8))
+#define MEMSIZE (LINESIZE * HEIGHT)
+
+int xenfb_connect_vkbd(const char *path)
+{
+ kbd_path = strdup(path);
+ return 0;
+}
+
+int xenfb_connect_vfb(const char *path)
+{
+ fb_path = strdup(path);
+ return 0;
+}
+
+static void xenfb_pv_update(DisplayState *s, int x, int y, int w, int h)
+{
+ struct fbfront_dev *fb_dev = s->opaque;
+ fbfront_update(fb_dev, x, y, w, h);
+}
+
+static void xenfb_pv_resize(DisplayState *s, int w, int h)
+{
+ struct fbfront_dev *fb_dev = s->opaque;
+ fprintf(stderr,"resize to %dx%d required\n", w, h);
+ s->width = w;
+ s->height = h;
+ /* TODO: send resize event if supported */
+ memset(s->data, 0, MEMSIZE);
+ fbfront_update(fb_dev, 0, 0, WIDTH, HEIGHT);
+}
+
+static void xenfb_pv_colourdepth(DisplayState *s, int depth)
+{
+ /* TODO: send redepth event if supported */
+ fprintf(stderr,"redepth to %d required\n", depth);
+}
+
+static void xenfb_kbd_handler(void *opaque)
+{
+#define KBD_NUM_BATCH 64
+ union xenkbd_in_event buf[KBD_NUM_BATCH];
+ int n, i;
+ DisplayState *s = opaque;
+ static int buttons;
+ static int x, y, z;
+
+ n = kbdfront_receive(kbd_dev, buf, KBD_NUM_BATCH);
+ for (i = 0; i < n; i++) {
+ switch (buf[i].type) {
+
+ case XENKBD_TYPE_MOTION:
+ fprintf(stderr, "FB backend sent us relative mouse motion event!\n");
+ break;
+
+ case XENKBD_TYPE_POS:
+ {
+ int new_x = buf[i].pos.abs_x;
+ int new_y = buf[i].pos.abs_y;
+ int new_z = buf[i].pos.abs_z;
+ if (new_x >= s->width)
+ new_x = s->width - 1;
+ if (new_y >= s->height)
+ new_y = s->height - 1;
+ if (kbd_mouse_is_absolute()) {
+ kbd_mouse_event(
+ new_x * 0x7FFF / (s->width - 1),
+ new_y * 0x7FFF / (s->height - 1),
+ new_z,
+ buttons);
+ } else {
+ kbd_mouse_event(
+ new_x - x,
+ new_y - y,
+ new_z - z,
+ buttons);
+ }
+ x = new_x;
+ y = new_y;
+ z = new_z;
+ break;
+ }
+
+ case XENKBD_TYPE_KEY:
+ {
+ int keycode = buf[i].key.keycode;
+ int button = 0;
+
+ if (keycode == BTN_LEFT)
+ button = MOUSE_EVENT_LBUTTON;
+ else if (keycode == BTN_RIGHT)
+ button = MOUSE_EVENT_RBUTTON;
+ else if (keycode == BTN_MIDDLE)
+ button = MOUSE_EVENT_MBUTTON;
+
+ if (button) {
+ if (buf[i].key.pressed)
+ buttons |= button;
+ else
+ buttons &= ~button;
+ if (kbd_mouse_is_absolute())
+ kbd_mouse_event(
+ x * 0x7FFF / s->width,
+ y * 0x7FFF / s->height,
+ z,
+ buttons);
+ else
+ kbd_mouse_event(0, 0, 0, buttons);
+ } else {
+ int scancode = linux2scancode[keycode];
+ if (!scancode) {
+ fprintf(stderr, "Can't convert keycode %x to scancode\n", keycode);
+ break;
+ }
+ if (scancode & 0x80) {
+ kbd_put_keycode(0xe0);
+ scancode &= 0x7f;
+ }
+ if (!buf[i].key.pressed)
+ scancode |= 0x80;
+ kbd_put_keycode(scancode);
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void xenfb_pv_refresh(DisplayState *ds)
+{
+ vga_hw_update();
+}
+
+static void kbdfront_thread(void *p)
+{
+ int scancode, keycode;
+ kbd_dev = init_kbdfront(p, 1);
+ if (!kbd_dev) {
+ fprintf(stderr,"can't open keyboard\n");
+ exit(1);
+ }
+ up(&kbd_sem);
+ for (scancode = 0; scancode < 128; scancode++) {
+ keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode]];
+ linux2scancode[keycode] = scancode;
+ keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode] | 0x80];
+ linux2scancode[keycode] = scancode | 0x80;
+ }
+}
+
+int xenfb_pv_display_init(DisplayState *ds)
+{
+ void *data;
+ struct fbfront_dev *fb_dev;
+ int kbd_fd;
+
+ if (!fb_path || !kbd_path)
+ return -1;
+
+ create_thread("kbdfront", kbdfront_thread, (void*) kbd_path);
+
+ data = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
+ fb_dev = init_fbfront(fb_path, data, WIDTH, HEIGHT, DEPTH, LINESIZE, MEMSIZE);
+ if (!fb_dev) {
+ fprintf(stderr,"can't open frame buffer\n");
+ exit(1);
+ }
+ free(fb_path);
+
+ down(&kbd_sem);
+ free(kbd_path);
+
+ kbd_fd = kbdfront_open(kbd_dev);
+ qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, ds);
+
+ ds->data = data;
+ ds->linesize = LINESIZE;
+ ds->depth = DEPTH;
+ ds->bgr = 0;
+ ds->width = WIDTH;
+ ds->height = HEIGHT;
+ ds->dpy_update = xenfb_pv_update;
+ ds->dpy_resize = xenfb_pv_resize;
+ ds->dpy_colourdepth = NULL; //xenfb_pv_colourdepth;
+ ds->dpy_refresh = xenfb_pv_refresh;
+ ds->opaque = fb_dev;
+ return 0;
+}
+#endif
+
/*
* Local variables:
* c-indent-level: 8
diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index f9a575043d..aaecb286a9 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -7831,6 +7831,10 @@ int main(int argc, char **argv)
init_ioports();
/* terminal init */
+#ifdef CONFIG_STUBDOM
+ if (xenfb_pv_display_init(ds) == 0) {
+ } else
+#endif
if (nographic) {
dumb_display_init(ds);
} else if (vnc_display != NULL || vncunused != 0) {
diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
index 0c5a9da97f..5c421cff9c 100644
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -1527,6 +1527,11 @@ int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
int xenstore_vm_write(int domid, char *key, char *val);
char *xenstore_vm_read(int domid, char *key, unsigned int *len);
+/* xenfb.c */
+int xenfb_pv_display_init(DisplayState *ds);
+int xenfb_connect_vkbd(const char *path);
+int xenfb_connect_vfb(const char *path);
+
/* helper2.c */
extern long time_offset;
void timeoffset_get(void);
diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c
index 843a10e875..e1c253221b 100644
--- a/tools/ioemu/xenstore.c
+++ b/tools/ioemu/xenstore.c
@@ -238,6 +238,37 @@ void xenstore_parse_domain_config(int domid)
}
}
+#ifdef CONFIG_STUBDOM
+ if (pasprintf(&buf, "%s/device/vkbd", path) == -1)
+ goto out;
+
+ free(e);
+ e = xs_directory(xsh, XBT_NULL, buf, &num);
+
+ if (e) {
+ for (i = 0; i < num; i++) {
+ if (pasprintf(&buf, "%s/device/vkbd/%s", path, e[i]) == -1)
+ continue;
+ xenfb_connect_vkbd(buf);
+ }
+ }
+
+ if (pasprintf(&buf, "%s/device/vfb", path) == -1)
+ goto out;
+
+ free(e);
+ e = xs_directory(xsh, XBT_NULL, buf, &num);
+
+ if (e) {
+ for (i = 0; i < num; i++) {
+ if (pasprintf(&buf, "%s/device/vfb/%s", path, e[i]) == -1)
+ continue;
+ xenfb_connect_vfb(buf);
+ }
+ }
+#endif
+
+
/* Set a watch for log-dirty requests from the migration tools */
if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
domid) != -1) {