ia64/xen-unstable

changeset 16229:290b460838a8

pv-qemu 2/10: Add a QEMU machine type for paravirt guests

This patch adds a paravirt machine type to QEMU. This can be requested
by passing the arg '-M xenpv' to qemu-dm. Aside from -d, and
-domain-name, the only other args that are processed are the VNC / SDL
graphics related args. Any others will be ignored. A tweak to
helper2.c was made to stop it setting up a file handler watch when
there are no CPUs registered.

The paravirt machine is in hw/xen_machine_pv.c and registers an
instance of the xenfb class, integrating it with the QEMU event loop
and key/mouse handlers. A couple of methods were adding to xenfb.h to
allow direct access to the file handles for xenstore & the event
channel.

The vfbif.py device controller is modified to launch qemu-dm instead
of the old xen-vncfb / sdlfb daemons.

When receiving framebuffer updates from the guest, the update has to
be copied into QEMU's copy of the framebuffer. This is because QEMU
stores the framebuffer in the format that is native to the SDL
display, or VNC client. This is not neccessarily the same as the guest
framebuffer which is always 32bpp. If there is an exact depth match we
use memcpy for speed, but in the non-matching case we have to fallback
to slow code to convert pixel formats. It fully supports all features
of the paravirt framebuffer including the choice between absolute &
relative pointers. The overall VIRT memory image size is about same as
old xen-vncfb, but the resident memory size is a little increased due
to copy of the framebuffer & some QEMU static state overhead. Most of
this is shared across QEMU processes.

To avoid both moving the xenfb.c and making changes to it in the same
patch, this just uses a Makefile hack to link against the xenfb.o from
the tools/xenfb/ directory. This will be removed in the following
patch.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
author Keir Fraser <keir@xensource.com>
date Thu Oct 25 14:35:04 2007 +0100 (2007-10-25)
parents 65b961265093
children 1ed990bc8da9
files tools/ioemu/Makefile.target tools/ioemu/hw/xen_machine_pv.c tools/ioemu/target-i386-dm/helper2.c tools/ioemu/vl.c tools/ioemu/vl.h tools/python/xen/xend/server/vfbif.py tools/xenfb/xenfb.c tools/xenfb/xenfb.h
line diff
     1.1 --- a/tools/ioemu/Makefile.target	Thu Oct 25 14:33:01 2007 +0100
     1.2 +++ b/tools/ioemu/Makefile.target	Thu Oct 25 14:35:04 2007 +0100
     1.3 @@ -410,6 +410,8 @@ VL_OBJS+= piix4acpi.o
     1.4  VL_OBJS+= xenstore.o
     1.5  VL_OBJS+= xen_platform.o
     1.6  VL_OBJS+= xen_machine_fv.o
     1.7 +VL_OBJS+= xen_machine_pv.o
     1.8 +VL_OBJS+= ../../xenfb/xenfb.o
     1.9  VL_OBJS+= tpm_tis.o
    1.10  CPPFLAGS += -DHAS_AUDIO
    1.11  endif
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/ioemu/hw/xen_machine_pv.c	Thu Oct 25 14:35:04 2007 +0100
     2.3 @@ -0,0 +1,315 @@
     2.4 +/*
     2.5 + * QEMU Xen PV Machine
     2.6 + *
     2.7 + * Copyright (c) 2007 Red Hat
     2.8 + *
     2.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    2.10 + * of this software and associated documentation files (the "Software"), to deal
    2.11 + * in the Software without restriction, including without limitation the rights
    2.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    2.13 + * copies of the Software, and to permit persons to whom the Software is
    2.14 + * furnished to do so, subject to the following conditions:
    2.15 + *
    2.16 + * The above copyright notice and this permission notice shall be included in
    2.17 + * all copies or substantial portions of the Software.
    2.18 + *
    2.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    2.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    2.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    2.25 + * THE SOFTWARE.
    2.26 + */
    2.27 +
    2.28 +#include "vl.h"
    2.29 +#include "../../xenfb/xenfb.h"
    2.30 +#include <linux/input.h>
    2.31 +
    2.32 +/*
    2.33 + * Tables to map from scancode to Linux input layer keycode.
    2.34 + * Scancodes are hardware-specific.  These maps assumes a 
    2.35 + * standard AT or PS/2 keyboard which is what QEMU feeds us.
    2.36 + */
    2.37 +static const unsigned char atkbd_set2_keycode[512] = {
    2.38 +
    2.39 +	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
    2.40 +	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
    2.41 +	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
    2.42 +	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
    2.43 +	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
    2.44 +	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
    2.45 +	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
    2.46 +	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
    2.47 +
    2.48 +	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    2.49 +	217,100,255,  0, 97,165,  0,  0,156,  0,  0,  0,  0,  0,  0,125,
    2.50 +	173,114,  0,113,  0,  0,  0,126,128,  0,  0,140,  0,  0,  0,127,
    2.51 +	159,  0,115,  0,164,  0,  0,116,158,  0,150,166,  0,  0,  0,142,
    2.52 +	157,  0,  0,  0,  0,  0,  0,  0,155,  0, 98,  0,  0,163,  0,  0,
    2.53 +	226,  0,  0,  0,  0,  0,  0,  0,  0,255, 96,  0,  0,  0,143,  0,
    2.54 +	  0,  0,  0,  0,  0,  0,  0,  0,  0,107,  0,105,102,  0,  0,112,
    2.55 +	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
    2.56 +
    2.57 +};
    2.58 +
    2.59 +static const unsigned char atkbd_unxlate_table[128] = {
    2.60 +
    2.61 +	  0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
    2.62 +	 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
    2.63 +	 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
    2.64 +	 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88,  5,  6,  4, 12,  3,
    2.65 +	 11,  2, 10,  1,  9,119,126,108,117,125,123,107,115,116,121,105,
    2.66 +	114,122,112,113,127, 96, 97,120,  7, 15, 23, 31, 39, 47, 55, 63,
    2.67 +	 71, 79, 86, 94,  8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
    2.68 +	 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
    2.69 +
    2.70 +};
    2.71 +
    2.72 +static unsigned char scancode2linux[512];
    2.73 +
    2.74 +/* A convenient function for munging pixels between different depths */
    2.75 +#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM)               \
    2.76 +    for (line = y ; line < h ; line++) {                                \
    2.77 +        SRC_T *src = (SRC_T *)(xenfb->pixels                            \
    2.78 +                               + (line * xenfb->row_stride)             \
    2.79 +                               + (x * xenfb->depth / 8));               \
    2.80 +        DST_T *dst = (DST_T *)(ds->data                                 \
    2.81 +                               + (line * ds->linesize)                  \
    2.82 +                               + (x * ds->depth / 8));                  \
    2.83 +        int col;                                                        \
    2.84 +        for (col = x ; col < w ; col++) {                               \
    2.85 +            *dst = (((*src >> RRS) & RM) << RLS) |                      \
    2.86 +                (((*src >> GRS) & GM) << GLS) |                         \
    2.87 +                (((*src >> GRS) & BM) << BLS);                          \
    2.88 +            src++;                                                      \
    2.89 +            dst++;                                                      \
    2.90 +        }                                                               \
    2.91 +    }
    2.92 +
    2.93 +/* This copies data from the guest framebuffer region, into QEMU's copy
    2.94 + * NB. QEMU's copy is stored in the pixel format of a) the local X 
    2.95 + * server (SDL case) or b) the current VNC client pixel format.
    2.96 + */
    2.97 +static void xen_pvfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h)
    2.98 +{
    2.99 +    DisplayState *ds = (DisplayState *)xenfb->user_data;
   2.100 +    int line;
   2.101 +
   2.102 +    if (xenfb->depth == ds->depth) { /* Perfect match can use fast path */
   2.103 +        for (line = y ; line < (y+h) ; line++) {
   2.104 +            memcpy(ds->data + (line * ds->linesize) + (x * ds->depth / 8),
   2.105 +                   xenfb->pixels + (line * xenfb->row_stride) + (x * xenfb->depth / 8),
   2.106 +                   w * xenfb->depth / 8);
   2.107 +        }
   2.108 +    } else { /* Mismatch requires slow pixel munging */
   2.109 +        if (xenfb->depth == 8) {
   2.110 +            /* 8 bit source == r:3 g:3 b:2 */
   2.111 +            if (ds->depth == 16) {
   2.112 +                BLT(uint8_t, uint16_t,   5, 2, 0,   11, 5, 0,   7, 7, 3);
   2.113 +            } else if (ds->depth == 32) {
   2.114 +                BLT(uint8_t, uint32_t,   5, 2, 0,   16, 8, 0,   7, 7, 3);
   2.115 +            }
   2.116 +        } else if (xenfb->depth == 16) {
   2.117 +            /* 16 bit source == r:5 g:6 b:5 */
   2.118 +            if (ds->depth == 8) {
   2.119 +                BLT(uint16_t, uint8_t,    11, 5, 0,   5, 2, 0,    31, 63, 31);
   2.120 +            } else if (ds->depth == 32) {
   2.121 +                BLT(uint16_t, uint32_t,   11, 5, 0,   16, 8, 0,   31, 63, 31);
   2.122 +            }
   2.123 +        } else if (xenfb->depth == 32) {
   2.124 +            /* 32 bit source == r:8 g:8 b:8 (padding:8) */
   2.125 +            if (ds->depth == 8) {
   2.126 +                BLT(uint32_t, uint8_t,    16, 8, 0,   5, 2, 0,    255, 255, 255);
   2.127 +            } else if (ds->depth == 16) {
   2.128 +                BLT(uint32_t, uint16_t,   16, 8, 0,   11, 5, 0,   255, 255, 255);
   2.129 +            }
   2.130 +        }
   2.131 +    }
   2.132 +    dpy_update(ds, x, y, w, h);
   2.133 +}
   2.134 +
   2.135 +/* 
   2.136 + * Send a key event from the client to the guest OS
   2.137 + * QEMU gives us a raw scancode from an AT / PS/2 style keyboard.
   2.138 + * We have to turn this into a Linux Input layer keycode.
   2.139 + * 
   2.140 + * Extra complexity from the fact that with extended scancodes 
   2.141 + * (like those produced by arrow keys) this method gets called
   2.142 + * twice, but we only want to send a single event. So we have to
   2.143 + * track the '0xe0' scancode state & collapse the extended keys
   2.144 + * as needed.
   2.145 + * 
   2.146 + * Wish we could just send scancodes straight to the guest which
   2.147 + * already has code for dealing with this...
   2.148 + */
   2.149 +static void xen_pvfb_key_event(void *opaque, int scancode)
   2.150 +{
   2.151 +    static int extended = 0;
   2.152 +    int down = 1;
   2.153 +    if (scancode == 0xe0) {
   2.154 +        extended = 1;
   2.155 +        return;
   2.156 +    } else if (scancode & 0x80) {
   2.157 +        scancode &= 0x7f;
   2.158 +        down = 0;
   2.159 +    }
   2.160 +    if (extended) {
   2.161 +        scancode |= 0x80;
   2.162 +        extended = 0;
   2.163 +    }
   2.164 +    xenfb_send_key(opaque, down, scancode2linux[scancode]);
   2.165 +}
   2.166 +
   2.167 +/*
   2.168 + * Send a mouse event from the client to the guest OS
   2.169 + * 
   2.170 + * The QEMU mouse can be in either relative, or absolute mode.
   2.171 + * Movement is sent separately from button state, which has to
   2.172 + * be encoded as virtual key events. We also don't actually get
   2.173 + * given any button up/down events, so have to track changes in
   2.174 + * the button state.
   2.175 + */
   2.176 +static void xen_pvfb_mouse_event(void *opaque,
   2.177 +                                 int dx, int dy, int dz, int button_state)
   2.178 +{
   2.179 +    static int old_state = 0;
   2.180 +    int i;
   2.181 +    struct xenfb *xenfb = opaque;
   2.182 +    DisplayState *ds = (DisplayState *)xenfb->user_data;
   2.183 +    if (xenfb->abs_pointer_wanted)
   2.184 +        xenfb_send_position(xenfb,
   2.185 +                            dx * ds->width / 0x7fff,
   2.186 +                            dy * ds->height / 0x7fff);
   2.187 +    else
   2.188 +        xenfb_send_motion(xenfb, dx, dy);
   2.189 +
   2.190 +	for (i = 0 ; i < 8 ; i++) {
   2.191 +		int lastDown = old_state & (1 << i);
   2.192 +		int down = button_state & (1 << i);
   2.193 +		if (down == lastDown)
   2.194 +			continue;
   2.195 +
   2.196 +		if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)
   2.197 +			return;
   2.198 +	}
   2.199 +    old_state = button_state;
   2.200 +}
   2.201 +
   2.202 +/* QEMU display state changed, so refresh the framebuffer copy */
   2.203 +/* XXX - can we optimize this, or the next func at all ? */ 
   2.204 +void xen_pvfb_update(void *opaque)
   2.205 +{
   2.206 +    struct xenfb *xenfb = opaque;
   2.207 +    xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);
   2.208 +}
   2.209 +
   2.210 +/* QEMU display state changed, so refresh the framebuffer copy */
   2.211 +void xen_pvfb_invalidate(void *opaque)
   2.212 +{
   2.213 +    xen_pvfb_update(opaque);
   2.214 +}
   2.215 +
   2.216 +/* Screen dump is not used in Xen, so no need to impl this ? */
   2.217 +void xen_pvfb_screen_dump(void *opaque, const char *name) { }
   2.218 +
   2.219 +void xen_pvfb_dispatch_store(void *opaque) {
   2.220 +    int ret;
   2.221 +    if ((ret = xenfb_dispatch_store(opaque)) < 0) {
   2.222 +        fprintf(stderr, "Failure while dispatching store: %d\n", ret);
   2.223 +        exit(1);
   2.224 +    }
   2.225 +}
   2.226 +
   2.227 +void xen_pvfb_dispatch_channel(void *opaque) {
   2.228 +    int ret;
   2.229 +    if ((ret = xenfb_dispatch_channel(opaque)) < 0) {
   2.230 +        fprintf(stderr, "Failure while dispatching store: %d\n", ret);
   2.231 +        exit(1);
   2.232 +    }
   2.233 +}
   2.234 +
   2.235 +/* The Xen PV machine currently provides
   2.236 + *   - a virtual framebuffer
   2.237 + *   - ....
   2.238 + */
   2.239 +static void xen_init_pv(uint64_t ram_size, int vga_ram_size, char *boot_device,
   2.240 +			DisplayState *ds, const char **fd_filename,
   2.241 +			int snapshot,
   2.242 +			const char *kernel_filename,
   2.243 +			const char *kernel_cmdline,
   2.244 +			const char *initrd_filename)
   2.245 +{
   2.246 +    struct xenfb *xenfb;
   2.247 +    extern int domid;
   2.248 +    int fd, i;
   2.249 +
   2.250 +    /* Prepare scancode mapping table */
   2.251 +	for (i = 0; i < 128; i++) {
   2.252 +		scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
   2.253 +		scancode2linux[i | 0x80] = 
   2.254 +			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
   2.255 +	}
   2.256 +
   2.257 +    /* Prepare PVFB state */
   2.258 +    xenfb = xenfb_new();
   2.259 +    if (xenfb == NULL) {
   2.260 +        fprintf(stderr, "Could not create framebuffer (%s)\n",
   2.261 +                strerror(errno));
   2.262 +        exit(1);
   2.263 +    }
   2.264 +
   2.265 +    /* Talk to the guest */
   2.266 +    if (xenfb_attach_dom(xenfb, domid) < 0) {
   2.267 +        fprintf(stderr, "Could not connect to domain (%s)\n",
   2.268 +                strerror(errno));
   2.269 +        exit(1);
   2.270 +    }
   2.271 +    xenfb->update = xen_pvfb_guest_copy;
   2.272 +    xenfb->user_data = ds;
   2.273 +
   2.274 +    /* Tell QEMU to allocate a graphical console */
   2.275 +    graphic_console_init(ds,
   2.276 +                         xen_pvfb_update,
   2.277 +                         xen_pvfb_invalidate,
   2.278 +                         xen_pvfb_screen_dump,
   2.279 +                         xenfb);
   2.280 +
   2.281 +    /* Register our keyboard & mouse handlers */
   2.282 +    qemu_add_kbd_event_handler(xen_pvfb_key_event, xenfb);
   2.283 +    qemu_add_mouse_event_handler(xen_pvfb_mouse_event, xenfb,
   2.284 +                                 xenfb->abs_pointer_wanted,
   2.285 +                                 "Xen PVFB Mouse");
   2.286 +
   2.287 +    /* Listen for events from xenstore */
   2.288 +    fd = xenfb_get_store_fd(xenfb);
   2.289 +    if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_store, NULL, xenfb) < 0) {
   2.290 +        fprintf(stderr, "Could not register event handler (%s)\n",
   2.291 +                strerror(errno));
   2.292 +    }
   2.293 +
   2.294 +    /* Listen for events from the event channel */
   2.295 +    fd = xenfb_get_channel_fd(xenfb);
   2.296 +    if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_channel, NULL, xenfb) < 0) {
   2.297 +        fprintf(stderr, "Could not register event handler (%s)\n",
   2.298 +                strerror(errno));
   2.299 +    }
   2.300 +
   2.301 +    /* Setup QEMU display */
   2.302 +    dpy_resize(ds, xenfb->width, xenfb->height);
   2.303 +}
   2.304 +
   2.305 +QEMUMachine xenpv_machine = {
   2.306 +    "xenpv",
   2.307 +    "Xen Para-virtualized PC",
   2.308 +    xen_init_pv,
   2.309 +};
   2.310 +
   2.311 +/*
   2.312 + * Local variables:
   2.313 + *  indent-tabs-mode: nil
   2.314 + *  c-indent-level: 4
   2.315 + *  c-basic-offset: 4
   2.316 + *  tab-width: 4
   2.317 + * End:
   2.318 + */
     3.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Thu Oct 25 14:33:01 2007 +0100
     3.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Thu Oct 25 14:35:04 2007 +0100
     3.3 @@ -616,7 +616,7 @@ int main_loop(void)
     3.4      extern int shutdown_requested;
     3.5      extern int suspend_requested;
     3.6      CPUState *env = cpu_single_env;
     3.7 -    int evtchn_fd = xc_evtchn_fd(xce_handle);
     3.8 +    int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle);
     3.9      char qemu_file[PATH_MAX];
    3.10      fd_set fds;
    3.11  
    3.12 @@ -624,7 +624,8 @@ int main_loop(void)
    3.13  				       cpu_single_env);
    3.14      qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock));
    3.15  
    3.16 -    qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
    3.17 +    if (evtchn_fd != -1)
    3.18 +        qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env);
    3.19  
    3.20      xenstore_record_dm_state("running");
    3.21      while (1) {
     4.1 --- a/tools/ioemu/vl.c	Thu Oct 25 14:33:01 2007 +0100
     4.2 +++ b/tools/ioemu/vl.c	Thu Oct 25 14:35:04 2007 +0100
     4.3 @@ -193,7 +193,7 @@ extern int vcpus;
     4.4  
     4.5  int xc_handle;
     4.6  
     4.7 -char domain_name[64] = "Xen-HVM-no-name";
     4.8 +char domain_name[64] = "Xen-no-name";
     4.9  extern int domid;
    4.10  
    4.11  char vncpasswd[64];
    4.12 @@ -6700,6 +6700,7 @@ void register_machines(void)
    4.13      qemu_register_machine(&isapc_machine);
    4.14  #else
    4.15      qemu_register_machine(&xenfv_machine);
    4.16 +    qemu_register_machine(&xenpv_machine);
    4.17  #endif
    4.18  #elif defined(TARGET_PPC)
    4.19      qemu_register_machine(&heathrow_machine);
    4.20 @@ -7446,7 +7447,7 @@ int main(int argc, char **argv)
    4.21                  break;
    4.22              case QEMU_OPTION_domainname:
    4.23                  snprintf(domain_name, sizeof(domain_name),
    4.24 -                         "Xen-HVM-%s", optarg);
    4.25 +                         "Xen-%s", optarg);
    4.26                  break;
    4.27              case QEMU_OPTION_d:
    4.28                  domid = atoi(optarg);
     5.1 --- a/tools/ioemu/vl.h	Thu Oct 25 14:33:01 2007 +0100
     5.2 +++ b/tools/ioemu/vl.h	Thu Oct 25 14:35:04 2007 +0100
     5.3 @@ -1110,6 +1110,7 @@ extern QEMUMachine pc_machine;
     5.4  extern QEMUMachine isapc_machine;
     5.5  #ifdef CONFIG_DM
     5.6  extern QEMUMachine xenfv_machine;
     5.7 +extern QEMUMachine xenpv_machine;
     5.8  #endif
     5.9  extern int fd_bootchk;
    5.10  
     6.1 --- a/tools/python/xen/xend/server/vfbif.py	Thu Oct 25 14:33:01 2007 +0100
     6.2 +++ b/tools/python/xen/xend/server/vfbif.py	Thu Oct 25 14:35:04 2007 +0100
     6.3 @@ -50,8 +50,10 @@ class VfbifController(DevController):
     6.4              # is HVM, so qemu-dm will handle the vfb.
     6.5              return
     6.6          
     6.7 -        std_args = [ "--domid", "%d" % self.vm.getDomid(),
     6.8 -                     "--title", self.vm.getName() ]
     6.9 +        args = [ xen.util.auxbin.pathTo("qemu-dm"),
    6.10 +                 "-M", "xenpv",
    6.11 +                 "-d", "%d" % self.vm.getDomid(),
    6.12 +                 "-domain-name", self.vm.getName() ]
    6.13          t = config.get("type", None)
    6.14          if t == "vnc":
    6.15              passwd = None
    6.16 @@ -65,15 +67,14 @@ class VfbifController(DevController):
    6.17              else:
    6.18                  log.debug("No VNC passwd configured for vfb access")
    6.19  
    6.20 -            # Try to start the vnc backend
    6.21 -            args = [xen.util.auxbin.pathTo("xen-vncfb")]
    6.22 -            if config.has_key("vncunused"):
    6.23 -                args += ["--unused"]
    6.24 -            elif config.has_key("vncdisplay"):
    6.25 -                args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))]
    6.26 -            vnclisten = config.get("vnclisten",
    6.27 +            vnclisten = config.get('vnclisten',
    6.28                                     xen.xend.XendOptions.instance().get_vnclisten_address())
    6.29 -            args += [ "--listen", vnclisten ]
    6.30 +            vncdisplay = config.get('vncdisplay', 0)
    6.31 +            args += ['-vnc', "%s:%d" % (vnclisten, vncdisplay)]
    6.32 +
    6.33 +            if config.get('vncunused', 0):
    6.34 +                args += ['-vncunused']
    6.35 +
    6.36              if config.has_key("keymap"):
    6.37                  args += ["-k", "%s" % config["keymap"]]
    6.38              else:
    6.39 @@ -81,15 +82,14 @@ class VfbifController(DevController):
    6.40                  if xoptions.get_keymap():
    6.41                      args += ["-k", "%s" % xoptions.get_keymap()]
    6.42  
    6.43 -            spawn_detached(args[0], args + std_args, os.environ)
    6.44 +            spawn_detached(args[0], args, os.environ)
    6.45          elif t == "sdl":
    6.46 -            args = [xen.util.auxbin.pathTo("xen-sdlfb")]
    6.47              env = dict(os.environ)
    6.48              if config.has_key("display"):
    6.49                  env['DISPLAY'] = config["display"]
    6.50              if config.has_key("xauthority"):
    6.51                  env['XAUTHORITY'] = config["xauthority"]
    6.52 -            spawn_detached(args[0], args + std_args, env)
    6.53 +            spawn_detached(args[0], args, env)
    6.54          else:
    6.55              raise VmError('Unknown vfb type %s (%s)' % (t, repr(config)))
    6.56  
     7.1 --- a/tools/xenfb/xenfb.c	Thu Oct 25 14:33:01 2007 +0100
     7.2 +++ b/tools/xenfb/xenfb.c	Thu Oct 25 14:35:04 2007 +0100
     7.3 @@ -670,37 +670,58 @@ static int xenfb_on_state_change(struct 
     7.4  	return 0;
     7.5  }
     7.6  
     7.7 -/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
     7.8 -int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
     7.9 +int xenfb_dispatch_channel(struct xenfb *xenfb_pub)
    7.10  {
    7.11  	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
    7.12  	evtchn_port_t port;
    7.13 +	port = xc_evtchn_pending(xenfb->evt_xch);
    7.14 +	if (port == -1)
    7.15 +		return -1;
    7.16 +
    7.17 +	if (port == xenfb->fb.port)
    7.18 +		xenfb_on_fb_event(xenfb);
    7.19 +	else if (port == xenfb->kbd.port)
    7.20 +		xenfb_on_kbd_event(xenfb);
    7.21 +
    7.22 +	if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
    7.23 +		return -1;
    7.24 +
    7.25 +	return 0;
    7.26 +}
    7.27 +
    7.28 +int xenfb_dispatch_store(struct xenfb *xenfb_pub)
    7.29 +{
    7.30 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
    7.31  	unsigned dummy;
    7.32  	char **vec;
    7.33  	int r;
    7.34  
    7.35 -	if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
    7.36 -		port = xc_evtchn_pending(xenfb->evt_xch);
    7.37 -		if (port == -1)
    7.38 -			return -1;
    7.39 +	vec = xs_read_watch(xenfb->xsh, &dummy);
    7.40 +	free(vec);
    7.41 +	r = xenfb_on_state_change(&xenfb->fb);
    7.42 +	if (r == 0)
    7.43 +		r = xenfb_on_state_change(&xenfb->kbd);
    7.44 +	if (r == -1)
    7.45 +		return -2;
    7.46  
    7.47 -		if (port == xenfb->fb.port)
    7.48 -			xenfb_on_fb_event(xenfb);
    7.49 -		else if (port == xenfb->kbd.port)
    7.50 -			xenfb_on_kbd_event(xenfb);
    7.51 +	return 0;
    7.52 +}
    7.53  
    7.54 -		if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
    7.55 -			return -1;
    7.56 +
    7.57 +/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
    7.58 +int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
    7.59 +{
    7.60 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
    7.61 +	int ret;
    7.62 +
    7.63 +	if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
    7.64 +		if ((ret = xenfb_dispatch_channel(xenfb_pub)) < 0)
    7.65 +			return ret;
    7.66  	}
    7.67  
    7.68  	if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
    7.69 -		vec = xs_read_watch(xenfb->xsh, &dummy);
    7.70 -		free(vec);
    7.71 -		r = xenfb_on_state_change(&xenfb->fb);
    7.72 -		if (r == 0)
    7.73 -			r = xenfb_on_state_change(&xenfb->kbd);
    7.74 -		if (r == -1)
    7.75 -			return -2;
    7.76 +		if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0)
    7.77 +			return ret;
    7.78  	}
    7.79  
    7.80  	return 0;
    7.81 @@ -717,6 +738,18 @@ int xenfb_select_fds(struct xenfb *xenfb
    7.82  	return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
    7.83  }
    7.84  
    7.85 +int xenfb_get_store_fd(struct xenfb *xenfb_pub)
    7.86 +{
    7.87 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
    7.88 +	return xs_fileno(xenfb->xsh);
    7.89 +}
    7.90 +
    7.91 +int xenfb_get_channel_fd(struct xenfb *xenfb_pub)
    7.92 +{
    7.93 +	struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
    7.94 +	return xc_evtchn_fd(xenfb->evt_xch);
    7.95 +}
    7.96 +
    7.97  static int xenfb_kbd_event(struct xenfb_private *xenfb,
    7.98  			   union xenkbd_in_event *event)
    7.99  {
   7.100 @@ -777,3 +810,10 @@ int xenfb_send_position(struct xenfb *xe
   7.101  
   7.102  	return xenfb_kbd_event(xenfb, &event);
   7.103  }
   7.104 +/*
   7.105 + * Local variables:
   7.106 + *  c-indent-level: 8
   7.107 + *  c-basic-offset: 8
   7.108 + *  tab-width: 8
   7.109 + * End:
   7.110 + */
     8.1 --- a/tools/xenfb/xenfb.h	Thu Oct 25 14:33:01 2007 +0100
     8.2 +++ b/tools/xenfb/xenfb.h	Thu Oct 25 14:35:04 2007 +0100
     8.3 @@ -25,8 +25,12 @@ void xenfb_teardown(struct xenfb *xenfb)
     8.4  
     8.5  int xenfb_attach_dom(struct xenfb *xenfb, int domid);
     8.6  
     8.7 +int xenfb_dispatch_store(struct xenfb *xenfb_pub);
     8.8 +int xenfb_dispatch_channel(struct xenfb *xenfb_pub);
     8.9  int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
    8.10  int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
    8.11 +int xenfb_get_store_fd(struct xenfb *xenfb_pub);
    8.12 +int xenfb_get_channel_fd(struct xenfb *xenfb_pub);
    8.13  
    8.14  int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
    8.15  int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);