diff options
-rw-r--r-- | extras/mini-os/fbfront.c | 12 | ||||
-rw-r--r-- | extras/mini-os/include/fbfront.h | 3 | ||||
-rw-r--r-- | stubdom/README | 75 | ||||
-rw-r--r-- | tools/ioemu/hw/xenfb.c | 210 | ||||
-rw-r--r-- | tools/ioemu/vl.c | 4 | ||||
-rw-r--r-- | tools/ioemu/vl.h | 5 | ||||
-rw-r--r-- | tools/ioemu/xenstore.c | 31 |
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) { |