ia64/xen-unstable

changeset 17142:b6cda88a3da6

stubdom: use PVFB so as to e.g. permit SDL display

This adds support in ioemu for PVFB frontend as stubdomain display.
This permits for instance to use SDL in dom0 to perform the eventual
display.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Feb 28 10:21:21 2008 +0000 (2008-02-28)
parents 45a24393a594
children e44c6b67a483
files extras/mini-os/fbfront.c extras/mini-os/include/fbfront.h stubdom/README tools/ioemu/hw/xenfb.c tools/ioemu/vl.c tools/ioemu/vl.h tools/ioemu/xenstore.c
line diff
     1.1 --- a/extras/mini-os/fbfront.c	Thu Feb 28 10:19:49 2008 +0000
     1.2 +++ b/extras/mini-os/fbfront.c	Thu Feb 28 10:21:21 2008 +0000
     1.3 @@ -31,13 +31,6 @@ struct kbdfront_dev {
     1.4      char *nodename;
     1.5      char *backend;
     1.6  
     1.7 -    char *data;
     1.8 -    int width;
     1.9 -    int height;
    1.10 -    int depth;
    1.11 -    int line_length;
    1.12 -    int mem_length;
    1.13 -
    1.14  #ifdef HAVE_LIBC
    1.15      int fd;
    1.16  #endif
    1.17 @@ -316,7 +309,10 @@ struct fbfront_dev *init_fbfront(char *n
    1.18      for (i = 0; mapped < mem_length && i < max_pd; i++) {
    1.19          unsigned long *pd = (unsigned long *) alloc_page();
    1.20          for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned long); j++) {
    1.21 -            pd[j] = virt_to_mfn((unsigned long) data + mapped);
    1.22 +            /* Trigger CoW */
    1.23 +            * ((char *)data + mapped) = 0;
    1.24 +            barrier();
    1.25 +            pd[j] = virtual_to_mfn((unsigned long) data + mapped);
    1.26              mapped += PAGE_SIZE;
    1.27          }
    1.28          for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
     2.1 --- a/extras/mini-os/include/fbfront.h	Thu Feb 28 10:19:49 2008 +0000
     2.2 +++ b/extras/mini-os/include/fbfront.h	Thu Feb 28 10:21:21 2008 +0000
     2.3 @@ -14,6 +14,9 @@
     2.4  #ifndef KEY_Q
     2.5  #define KEY_Q 16
     2.6  #endif
     2.7 +#ifndef KEY_MAX
     2.8 +#define KEY_MAX 0x1ff
     2.9 +#endif
    2.10  
    2.11  
    2.12  struct kbdfront_dev;
     3.1 --- a/stubdom/README	Thu Feb 28 10:19:49 2008 +0000
     3.2 +++ b/stubdom/README	Thu Feb 28 10:21:21 2008 +0000
     3.3 @@ -6,6 +6,73 @@ Then make install to install the result.
     3.4  
     3.5  Also, run make and make install in $XEN_ROOT/tools/fs-back
     3.6  
     3.7 +General Configuration
     3.8 +=====================
     3.9 +
    3.10 +In your HVM config "hvmconfig",
    3.11 +
    3.12 +- use /usr/lib/xen/bin/stubdom-dm as dm script
    3.13 +
    3.14 +device_model = '/usr/lib/xen/bin/stubdom-dm'
    3.15 +
    3.16 +- comment the disk statement:
    3.17 +
    3.18 +#disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
    3.19 +
    3.20 +
    3.21 +Create /etc/xen/stubdom-hvmconfig (where "hvmconfig" is the name of your HVM
    3.22 +guest) with
    3.23 +
    3.24 +kernel = "/usr/lib/xen/boot/stubdom.gz"
    3.25 +vif = [ '', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
    3.26 +disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
    3.27 +
    3.28 +where
    3.29 +- the first vif ('') is reserved for VNC (see below)
    3.30 +- 'ip=10.0.1.1,mac= etc...' is the same net configuration as in the hvmconfig
    3.31 +script,
    3.32 +- and disk = is the same block configuration as in the hvmconfig script.
    3.33 +
    3.34 +Display Configuration
    3.35 +=====================
    3.36 +
    3.37 +There are three posibilities
    3.38 +
    3.39 +* Using SDL
    3.40 +
    3.41 +In hvmconfig, disable vnc:
    3.42 +
    3.43 +vnc = 0
    3.44 +
    3.45 +In stubdom-hvmconfig, set a vfb:
    3.46 +
    3.47 +vfb = [ 'type=sdl' ]
    3.48 +
    3.49 +* Using a VNC server in the stub domain
    3.50 +
    3.51 +In hvmconfig, set vnclisten to "172.30.206.1" for instance.  Do not use a host
    3.52 +name as Mini-OS does not have a name resolver.  Do not use 127.0.0.1 since then
    3.53 +you will not be able to connect to it.
    3.54 +
    3.55 +vnc = 1
    3.56 +vnclisten = "172.30.206.1"
    3.57 +
    3.58 +In stubdom-hvmconfig, fill the reserved vif with the same IP, for instance:
    3.59 +
    3.60 +vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
    3.61 +
    3.62 +* Using a VNC server in dom0
    3.63 +
    3.64 +In hvmconfig, disable vnc:
    3.65 +
    3.66 +vnc = 0
    3.67 +
    3.68 +In stubdom-hvmconfig, set a vfb:
    3.69 +
    3.70 +vfb = [ 'type=vnc' ]
    3.71 +
    3.72 +and any other parameter as wished.
    3.73 +
    3.74  To run
    3.75  ======
    3.76  
    3.77 @@ -13,32 +80,4 @@ mkdir -p /exports/usr/share/qemu
    3.78  ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu
    3.79  /usr/sbin/fs-backend &
    3.80  
    3.81 -
    3.82 -In your HVM config "hvmconfig",
    3.83 -
    3.84 -- use VNC, set vnclisten to "172.30.206.1" for instance.  Do not use a host name
    3.85 -as Mini-OS does not have a name resolver.  Do not use 127.0.0.1 since then you
    3.86 -will not be able to connect to it.
    3.87 -
    3.88 -vnc = 1
    3.89 -vnclisten = "172.30.206.1"
    3.90 -
    3.91 -- use /usr/lib/xen/bin/stubdom-dm as dm script
    3.92 -
    3.93 -device_model = '/usr/lib/xen/bin/stubdom-dm'
    3.94 -
    3.95 -- comment the disk statement:
    3.96 -#disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
    3.97 -
    3.98 -Create /etc/xen/stubdom-hvmconfig (where "hvmconfig" is your HVM guest domain
    3.99 -name) with
   3.100 -
   3.101 -kernel = "/usr/lib/xen/boot/stubdom.gz"
   3.102 -vif = [ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34']
   3.103 -disk = [  'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ]
   3.104 -
   3.105 -where
   3.106 -- 172.30.206.1 is the IP for vnc,
   3.107 -- 'ip=10.0.1.1,mac= etc...' is the same net configuration as in the hvmconfig
   3.108 -script,
   3.109 -- and disk = is the same block configuration as in the hvmconfig script.
   3.110 +xm create hvmconfig
     4.1 --- a/tools/ioemu/hw/xenfb.c	Thu Feb 28 10:19:49 2008 +0000
     4.2 +++ b/tools/ioemu/hw/xenfb.c	Thu Feb 28 10:21:21 2008 +0000
     4.3 @@ -19,6 +19,12 @@
     4.4  
     4.5  #include "xenfb.h"
     4.6  
     4.7 +#ifdef CONFIG_STUBDOM
     4.8 +#include <semaphore.h>
     4.9 +#include <sched.h>
    4.10 +#include <fbfront.h>
    4.11 +#endif
    4.12 +
    4.13  #ifndef BTN_LEFT
    4.14  #define BTN_LEFT 0x110 /* from <linux/input.h> */
    4.15  #endif
    4.16 @@ -1124,12 +1130,10 @@ static void xenfb_guest_copy(struct xenf
    4.17      dpy_update(xenfb->ds, x, y, w, h);
    4.18  }
    4.19  
    4.20 -/* QEMU display state changed, so refresh the framebuffer copy */
    4.21 -/* XXX - can we optimize this, or the next func at all ? */ 
    4.22 +/* Periodic update of display, no need for any in our case */
    4.23  static void xenfb_update(void *opaque)
    4.24  {
    4.25      struct xenfb *xenfb = opaque;
    4.26 -    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
    4.27  }
    4.28  
    4.29  /* QEMU display state changed, so refresh the framebuffer copy */
    4.30 @@ -1169,6 +1173,206 @@ static int xenfb_register_console(struct
    4.31          return 0;
    4.32  }
    4.33  
    4.34 +#ifdef CONFIG_STUBDOM
    4.35 +static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0);
    4.36 +static struct kbdfront_dev *kbd_dev;
    4.37 +static char *kbd_path, *fb_path;
    4.38 +
    4.39 +static unsigned char linux2scancode[KEY_MAX + 1];
    4.40 +
    4.41 +#define WIDTH 1024
    4.42 +#define HEIGHT 768
    4.43 +#define DEPTH 32
    4.44 +#define LINESIZE (1280 * (DEPTH / 8))
    4.45 +#define MEMSIZE (LINESIZE * HEIGHT)
    4.46 +
    4.47 +int xenfb_connect_vkbd(const char *path)
    4.48 +{
    4.49 +    kbd_path = strdup(path);
    4.50 +    return 0;
    4.51 +}
    4.52 +
    4.53 +int xenfb_connect_vfb(const char *path)
    4.54 +{
    4.55 +    fb_path = strdup(path);
    4.56 +    return 0;
    4.57 +}
    4.58 +
    4.59 +static void xenfb_pv_update(DisplayState *s, int x, int y, int w, int h)
    4.60 +{
    4.61 +    struct fbfront_dev *fb_dev = s->opaque;
    4.62 +    fbfront_update(fb_dev, x, y, w, h);
    4.63 +}
    4.64 +
    4.65 +static void xenfb_pv_resize(DisplayState *s, int w, int h)
    4.66 +{
    4.67 +    struct fbfront_dev *fb_dev = s->opaque;
    4.68 +    fprintf(stderr,"resize to %dx%d required\n", w, h);
    4.69 +    s->width = w;
    4.70 +    s->height = h;
    4.71 +    /* TODO: send resize event if supported */
    4.72 +    memset(s->data, 0, MEMSIZE);
    4.73 +    fbfront_update(fb_dev, 0, 0, WIDTH, HEIGHT);
    4.74 +}
    4.75 +
    4.76 +static void xenfb_pv_colourdepth(DisplayState *s, int depth)
    4.77 +{
    4.78 +    /* TODO: send redepth event if supported */
    4.79 +    fprintf(stderr,"redepth to %d required\n", depth);
    4.80 +}
    4.81 +
    4.82 +static void xenfb_kbd_handler(void *opaque)
    4.83 +{
    4.84 +#define KBD_NUM_BATCH 64
    4.85 +    union xenkbd_in_event buf[KBD_NUM_BATCH];
    4.86 +    int n, i;
    4.87 +    DisplayState *s = opaque;
    4.88 +    static int buttons;
    4.89 +    static int x, y, z;
    4.90 +
    4.91 +    n = kbdfront_receive(kbd_dev, buf, KBD_NUM_BATCH);
    4.92 +    for (i = 0; i < n; i++) {
    4.93 +        switch (buf[i].type) {
    4.94 +
    4.95 +            case XENKBD_TYPE_MOTION:
    4.96 +                fprintf(stderr, "FB backend sent us relative mouse motion event!\n");
    4.97 +                break;
    4.98 +
    4.99 +            case XENKBD_TYPE_POS:
   4.100 +            {
   4.101 +                int new_x = buf[i].pos.abs_x;
   4.102 +                int new_y = buf[i].pos.abs_y;
   4.103 +                int new_z = buf[i].pos.abs_z;
   4.104 +                if (new_x >= s->width)
   4.105 +                    new_x = s->width - 1;
   4.106 +                if (new_y >= s->height)
   4.107 +                    new_y = s->height - 1;
   4.108 +                if (kbd_mouse_is_absolute()) {
   4.109 +                    kbd_mouse_event(
   4.110 +                            new_x * 0x7FFF / (s->width - 1),
   4.111 +                            new_y * 0x7FFF / (s->height - 1),
   4.112 +                            new_z,
   4.113 +                            buttons);
   4.114 +                } else {
   4.115 +                    kbd_mouse_event(
   4.116 +                            new_x - x,
   4.117 +                            new_y - y,
   4.118 +                            new_z - z,
   4.119 +                            buttons);
   4.120 +                }
   4.121 +                x = new_x;
   4.122 +                y = new_y;
   4.123 +                z = new_z;
   4.124 +                break;
   4.125 +            }
   4.126 +
   4.127 +            case XENKBD_TYPE_KEY:
   4.128 +            {
   4.129 +                int keycode = buf[i].key.keycode;
   4.130 +                int button = 0;
   4.131 +
   4.132 +                if (keycode == BTN_LEFT)
   4.133 +                    button = MOUSE_EVENT_LBUTTON;
   4.134 +                else if (keycode == BTN_RIGHT)
   4.135 +                    button = MOUSE_EVENT_RBUTTON;
   4.136 +                else if (keycode == BTN_MIDDLE)
   4.137 +                    button = MOUSE_EVENT_MBUTTON;
   4.138 +
   4.139 +                if (button) {
   4.140 +                    if (buf[i].key.pressed)
   4.141 +                        buttons |=  button;
   4.142 +                    else
   4.143 +                        buttons &= ~button;
   4.144 +                    if (kbd_mouse_is_absolute())
   4.145 +                        kbd_mouse_event(
   4.146 +                                x * 0x7FFF / s->width,
   4.147 +                                y * 0x7FFF / s->height,
   4.148 +                                z,
   4.149 +                                buttons);
   4.150 +                    else
   4.151 +                        kbd_mouse_event(0, 0, 0, buttons);
   4.152 +                } else {
   4.153 +                    int scancode = linux2scancode[keycode];
   4.154 +                    if (!scancode) {
   4.155 +                        fprintf(stderr, "Can't convert keycode %x to scancode\n", keycode);
   4.156 +                        break;
   4.157 +                    }
   4.158 +                    if (scancode & 0x80) {
   4.159 +                        kbd_put_keycode(0xe0);
   4.160 +                        scancode &= 0x7f;
   4.161 +                    }
   4.162 +                    if (!buf[i].key.pressed)
   4.163 +                        scancode |= 0x80;
   4.164 +                    kbd_put_keycode(scancode);
   4.165 +                }
   4.166 +                break;
   4.167 +            }
   4.168 +        }
   4.169 +    }
   4.170 +}
   4.171 +
   4.172 +static void xenfb_pv_refresh(DisplayState *ds)
   4.173 +{
   4.174 +    vga_hw_update();
   4.175 +}
   4.176 +
   4.177 +static void kbdfront_thread(void *p)
   4.178 +{
   4.179 +    int scancode, keycode;
   4.180 +    kbd_dev = init_kbdfront(p, 1);
   4.181 +    if (!kbd_dev) {
   4.182 +        fprintf(stderr,"can't open keyboard\n");
   4.183 +        exit(1);
   4.184 +    }
   4.185 +    up(&kbd_sem);
   4.186 +    for (scancode = 0; scancode < 128; scancode++) {
   4.187 +        keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode]];
   4.188 +        linux2scancode[keycode] = scancode;
   4.189 +        keycode = atkbd_set2_keycode[atkbd_unxlate_table[scancode] | 0x80];
   4.190 +        linux2scancode[keycode] = scancode | 0x80;
   4.191 +    }
   4.192 +}
   4.193 +
   4.194 +int xenfb_pv_display_init(DisplayState *ds)
   4.195 +{
   4.196 +    void *data;
   4.197 +    struct fbfront_dev *fb_dev;
   4.198 +    int kbd_fd;
   4.199 +
   4.200 +    if (!fb_path || !kbd_path)
   4.201 +        return -1;
   4.202 +
   4.203 +    create_thread("kbdfront", kbdfront_thread, (void*) kbd_path);
   4.204 +
   4.205 +    data = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
   4.206 +    fb_dev = init_fbfront(fb_path, data, WIDTH, HEIGHT, DEPTH, LINESIZE, MEMSIZE);
   4.207 +    if (!fb_dev) {
   4.208 +        fprintf(stderr,"can't open frame buffer\n");
   4.209 +        exit(1);
   4.210 +    }
   4.211 +    free(fb_path);
   4.212 +
   4.213 +    down(&kbd_sem);
   4.214 +    free(kbd_path);
   4.215 +
   4.216 +    kbd_fd = kbdfront_open(kbd_dev);
   4.217 +    qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, ds);
   4.218 +
   4.219 +    ds->data = data;
   4.220 +    ds->linesize = LINESIZE;
   4.221 +    ds->depth = DEPTH;
   4.222 +    ds->bgr = 0;
   4.223 +    ds->width = WIDTH;
   4.224 +    ds->height = HEIGHT;
   4.225 +    ds->dpy_update = xenfb_pv_update;
   4.226 +    ds->dpy_resize = xenfb_pv_resize;
   4.227 +    ds->dpy_colourdepth = NULL; //xenfb_pv_colourdepth;
   4.228 +    ds->dpy_refresh = xenfb_pv_refresh;
   4.229 +    ds->opaque = fb_dev;
   4.230 +    return 0;
   4.231 +}
   4.232 +#endif
   4.233 +
   4.234  /*
   4.235   * Local variables:
   4.236   *  c-indent-level: 8
     5.1 --- a/tools/ioemu/vl.c	Thu Feb 28 10:19:49 2008 +0000
     5.2 +++ b/tools/ioemu/vl.c	Thu Feb 28 10:21:21 2008 +0000
     5.3 @@ -7831,6 +7831,10 @@ int main(int argc, char **argv)
     5.4      init_ioports();
     5.5  
     5.6      /* terminal init */
     5.7 +#ifdef CONFIG_STUBDOM
     5.8 +    if (xenfb_pv_display_init(ds) == 0) {
     5.9 +    } else
    5.10 +#endif
    5.11      if (nographic) {
    5.12          dumb_display_init(ds);
    5.13      } else if (vnc_display != NULL || vncunused != 0) {
     6.1 --- a/tools/ioemu/vl.h	Thu Feb 28 10:19:49 2008 +0000
     6.2 +++ b/tools/ioemu/vl.h	Thu Feb 28 10:21:21 2008 +0000
     6.3 @@ -1527,6 +1527,11 @@ int xenstore_unsubscribe_from_hotplug_st
     6.4  int xenstore_vm_write(int domid, char *key, char *val);
     6.5  char *xenstore_vm_read(int domid, char *key, unsigned int *len);
     6.6  
     6.7 +/* xenfb.c */
     6.8 +int xenfb_pv_display_init(DisplayState *ds);
     6.9 +int xenfb_connect_vkbd(const char *path);
    6.10 +int xenfb_connect_vfb(const char *path);
    6.11 +
    6.12  /* helper2.c */
    6.13  extern long time_offset;
    6.14  void timeoffset_get(void);
     7.1 --- a/tools/ioemu/xenstore.c	Thu Feb 28 10:19:49 2008 +0000
     7.2 +++ b/tools/ioemu/xenstore.c	Thu Feb 28 10:21:21 2008 +0000
     7.3 @@ -238,6 +238,37 @@ void xenstore_parse_domain_config(int do
     7.4          }
     7.5      }
     7.6  
     7.7 +#ifdef CONFIG_STUBDOM
     7.8 +    if (pasprintf(&buf, "%s/device/vkbd", path) == -1)
     7.9 +        goto out;
    7.10 +
    7.11 +    free(e);
    7.12 +    e = xs_directory(xsh, XBT_NULL, buf, &num);
    7.13 +
    7.14 +    if (e) {
    7.15 +        for (i = 0; i < num; i++) {
    7.16 +            if (pasprintf(&buf, "%s/device/vkbd/%s", path, e[i]) == -1)
    7.17 +                continue;
    7.18 +            xenfb_connect_vkbd(buf);
    7.19 +        }
    7.20 +    }
    7.21 +
    7.22 +    if (pasprintf(&buf, "%s/device/vfb", path) == -1)
    7.23 +        goto out;
    7.24 +
    7.25 +    free(e);
    7.26 +    e = xs_directory(xsh, XBT_NULL, buf, &num);
    7.27 +
    7.28 +    if (e) {
    7.29 +        for (i = 0; i < num; i++) {
    7.30 +            if (pasprintf(&buf, "%s/device/vfb/%s", path, e[i]) == -1)
    7.31 +                continue;
    7.32 +            xenfb_connect_vfb(buf);
    7.33 +        }
    7.34 +    }
    7.35 +#endif
    7.36 +
    7.37 +
    7.38      /* Set a watch for log-dirty requests from the migration tools */
    7.39      if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
    7.40                    domid) != -1) {