diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/xen_machine_pv.c xen-3.1.2-src.new/tools/ioemu/hw/xen_machine_pv.c --- xen-3.1.2-src.orig/tools/ioemu/hw/xen_machine_pv.c 1969-12-31 19:00:00.000000000 -0500 +++ xen-3.1.2-src.new/tools/ioemu/hw/xen_machine_pv.c 2007-12-01 14:49:01.000000000 -0500 @@ -0,0 +1,231 @@ +/* + * QEMU Xen PV Machine + * + * Copyright (c) 2007 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "vl.h" +#include "../../xenfb/xenfb.h" +#include + +/* A convenient function for munging pixels between different depths */ +#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM) \ + for (line = y ; line < h ; line++) { \ + SRC_T *src = (SRC_T *)(xenfb->pixels + (line*xenfb->row_stride) + (x*xenfb->depth/8)); \ + DST_T *dst = (DST_T *)(ds->data + (line*ds->linesize) + (x*ds->depth/8)); \ + int col; \ + for (col = x ; col < w ; col++) { \ + *dst = (((*src >> RRS)&RM) << RLS) | \ + (((*src >> GRS)&GM) << GLS) | \ + (((*src >> GRS)&BM) << BLS); \ + src++; \ + dst++; \ + } \ + } + + +/* This copies data from the guest framebuffer region, into QEMU's copy + * NB. QEMU's copy is stored in the pixel format of a) the local X server (SDL case) + * or b) the current VNC client pixel format. + */ +static void xen_pvfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h) +{ + DisplayState *ds = (DisplayState *)xenfb->user_data; + int line; + + if (xenfb->depth == ds->depth) { /* Perfect match can use fast path */ + for (line = y ; line < (y+h) ; line++) { + memcpy(ds->data + (line * ds->linesize) + (x*ds->depth/8), + xenfb->pixels + (line*xenfb->row_stride) + (x*xenfb->depth/8), + w * xenfb->depth/8); + } + } else { /* Mismatch requires slow pixel munging */ + if (xenfb->depth == 8) { + /* 8 bit source == r:3 g:3 b:2 */ + if (ds->depth == 16) { + BLT(uint8_t, uint16_t, 5, 2, 0, 11, 5, 0, 7, 7, 3); + } else if (ds->depth == 32) { + BLT(uint8_t, uint32_t, 5, 2, 0, 16, 8, 0, 7, 7, 3); + } + } else if (xenfb->depth == 16) { + /* 16 bit source == r:5 g:6 b:5 */ + if (ds->depth == 8) { + BLT(uint16_t, uint8_t, 11, 5, 0, 5, 2, 0, 31, 63, 31); + } else if (ds->depth == 32) { + BLT(uint16_t, uint32_t, 11, 5, 0, 16, 8, 0, 31, 63, 31); + } + } else if (xenfb->depth == 32) { + /* 32 bit source == r:8 g:8 b:8 (padding:8) */ + if (ds->depth == 8) { + BLT(uint32_t, uint8_t, 16, 8, 0, 5, 2, 0, 255, 255, 255); + } else if (ds->depth == 16) { + BLT(uint32_t, uint16_t, 16, 8, 0, 11, 5, 0, 255, 255, 255); + } + } + } + dpy_update(ds, x, y, w, h); +} + + +/* Send a keypress from the client to the guest OS */ +static void xen_pvfb_put_keycode(void *opaque, int keycode) +{ + struct xenfb *xenfb = (struct xenfb*)opaque; + xenfb_send_key(xenfb, keycode & 0x80 ? 0 : 1, keycode & 0x7f); +} + +/* Send a mouse event from the client to the guest OS */ +static void xen_pvfb_mouse_event(void *opaque, + int dx, int dy, int dz, int button_state) +{ + static int old_state = 0; + int i; + struct xenfb *xenfb = (struct xenfb*)opaque; + DisplayState *ds = (DisplayState *)xenfb->user_data; + if (xenfb->abs_pointer_wanted) + xenfb_send_position(xenfb, + dx*ds->width/0x7fff, + dy*ds->height/0x7fff); + else + xenfb_send_motion(xenfb, dx, dy); + + for (i = 0 ; i < 8 ; i++) { + int lastDown = old_state & (1 << i); + int down = button_state & (1 << i); + if (down == lastDown) + continue; + + if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) + return; + } + old_state = button_state; +} + +/* QEMU display state changed, so refresh the framebuffer copy */ +void xen_pvfb_update(void *opaque) +{ + struct xenfb *xenfb = (struct xenfb *)opaque; + xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); +} + +/* QEMU display state changed, so refresh the framebuffer copy */ +void xen_pvfb_invalidate(void *opaque) +{ + struct xenfb *xenfb = (struct xenfb *)opaque; + xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); +} + +/* Screen dump is not used in Xen, so no need to impl this ? */ +void xen_pvfb_screen_dump(void *opaque, const char *name) { } + +void xen_pvfb_dispatch_store(void *opaque) { + int ret; + if ((ret = xenfb_dispatch_store((struct xenfb *)opaque)) < 0) { + fprintf(stderr, "Failure while dispatching store: %d\n", ret); + exit(1); + } +} + +void xen_pvfb_dispatch_channel(void *opaque) { + int ret; + if ((ret = xenfb_dispatch_channel((struct xenfb *)opaque)) < 0) { + fprintf(stderr, "Failure while dispatching store: %d\n", ret); + exit(1); + } +} + +/* The Xen PV machine currently provides + * - a virtual framebuffer + * - .... + */ +static void xen_init_pv(uint64_t ram_size, int vga_ram_size, char *boot_device, + DisplayState *ds, const char **fd_filename, + int snapshot, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, time_t timeoffset) +{ + struct xenfb *xenfb; + extern int domid; + int fd; + + /* Prepare PVFB state */ + xenfb = xenfb_new(); + if (xenfb == NULL) { + fprintf(stderr, "Could not create framebuffer (%s)\n", + strerror(errno)); + exit(1); + } + + /* Talk to the guest */ + if (xenfb_attach_dom(xenfb, domid) < 0) { + fprintf(stderr, "Could not connect to domain (%s)\n", + strerror(errno)); + exit(1); + } + xenfb->update = xen_pvfb_guest_copy; + xenfb->user_data = ds; + + /* Tell QEMU to allocate a graphical console */ + graphic_console_init(ds, + xen_pvfb_update, + xen_pvfb_invalidate, + xen_pvfb_screen_dump, + xenfb); + + /* Register our keyboard & mouse handlers */ + qemu_add_kbd_event_handler(xen_pvfb_put_keycode, xenfb); + qemu_add_mouse_event_handler(xen_pvfb_mouse_event, xenfb, + xenfb->abs_pointer_wanted + ); + + /* Listen for events from xenstore */ + fd = xenfb_get_store_fd(xenfb); + if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_store, NULL, xenfb) < 0) { + fprintf(stderr, "Could not register event handler (%s)\n", + strerror(errno)); + } + + /* Listen for events from the event channel */ + fd = xenfb_get_channel_fd(xenfb); + if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_channel, NULL, xenfb) < 0) { + fprintf(stderr, "Could not register event handler (%s)\n", + strerror(errno)); + } + + /* Setup QEMU display */ + dpy_resize(ds, xenfb->width, xenfb->height); +} + +QEMUMachine xenpv_machine = { + "xenpv", + "Xen Para-virtualized PC", + xen_init_pv, +}; + +/* + * Local variables: + * indent-tabs-mode: nil + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff -rupN xen-3.1.2-src.orig/tools/ioemu/Makefile.target xen-3.1.2-src.new/tools/ioemu/Makefile.target --- xen-3.1.2-src.orig/tools/ioemu/Makefile.target 2007-12-01 14:48:49.000000000 -0500 +++ xen-3.1.2-src.new/tools/ioemu/Makefile.target 2007-12-01 14:49:01.000000000 -0500 @@ -370,6 +370,8 @@ VL_OBJS+= piix4acpi.o VL_OBJS+= xenstore.o VL_OBJS+= xen_platform.o VL_OBJS+= xen_machine_fv.o +VL_OBJS+= xen_machine_pv.o +VL_OBJS+= ../../xenfb/xenfb.o VL_OBJS+= tpm_tis.o DEFINES += -DHAS_AUDIO endif diff -rupN xen-3.1.2-src.orig/tools/ioemu/target-i386-dm/helper2.c xen-3.1.2-src.new/tools/ioemu/target-i386-dm/helper2.c --- xen-3.1.2-src.orig/tools/ioemu/target-i386-dm/helper2.c 2007-12-01 14:47:23.000000000 -0500 +++ xen-3.1.2-src.new/tools/ioemu/target-i386-dm/helper2.c 2007-12-01 14:49:01.000000000 -0500 @@ -616,14 +616,15 @@ int main_loop(void) extern int shutdown_requested; extern int suspend_requested; CPUState *env = cpu_single_env; - int evtchn_fd = xc_evtchn_fd(xce_handle); + int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle); char qemu_file[PATH_MAX]; buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, cpu_single_env); qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); - qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); + if (evtchn_fd != -1) + qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); while (!(vm_running && suspend_requested)) /* Wait up to 10 msec. */ diff -rupN xen-3.1.2-src.orig/tools/ioemu/vl.c xen-3.1.2-src.new/tools/ioemu/vl.c --- xen-3.1.2-src.orig/tools/ioemu/vl.c 2007-12-01 14:48:49.000000000 -0500 +++ xen-3.1.2-src.new/tools/ioemu/vl.c 2007-12-01 14:49:01.000000000 -0500 @@ -168,7 +168,7 @@ int xc_handle; time_t timeoffset = 0; -char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'}; +char domain_name[1024] = "Xen-no-name"; extern int domid; char vncpasswd[64]; @@ -5700,6 +5700,7 @@ void register_machines(void) qemu_register_machine(&isapc_machine); #else qemu_register_machine(&xenfv_machine); + qemu_register_machine(&xenpv_machine); #endif #elif defined(TARGET_PPC) qemu_register_machine(&heathrow_machine); @@ -6395,7 +6396,8 @@ int main(int argc, char **argv) acpi_enabled = 0; break; case QEMU_OPTION_domainname: - strncat(domain_name, optarg, sizeof(domain_name) - 20); + snprintf(domain_name, sizeof(domain_name), + "Xen-%s", optarg); break; case QEMU_OPTION_d: domid = atoi(optarg); diff -rupN xen-3.1.2-src.orig/tools/ioemu/vl.h xen-3.1.2-src.new/tools/ioemu/vl.h --- xen-3.1.2-src.orig/tools/ioemu/vl.h 2007-12-01 14:48:49.000000000 -0500 +++ xen-3.1.2-src.new/tools/ioemu/vl.h 2007-12-01 14:49:01.000000000 -0500 @@ -967,6 +967,7 @@ extern QEMUMachine pc_machine; extern QEMUMachine isapc_machine; #ifdef CONFIG_DM extern QEMUMachine xenfv_machine; +extern QEMUMachine xenpv_machine; #endif extern int fd_bootchk; diff -rupN xen-3.1.2-src.orig/tools/python/xen/xend/server/vfbif.py xen-3.1.2-src.new/tools/python/xen/xend/server/vfbif.py --- xen-3.1.2-src.orig/tools/python/xen/xend/server/vfbif.py 2007-11-14 18:35:27.000000000 -0500 +++ xen-3.1.2-src.new/tools/python/xen/xend/server/vfbif.py 2007-12-01 14:51:55.000000000 -0500 @@ -6,6 +6,7 @@ import xen.xend import os def spawn_detached(path, args, env): + log.debug("Spawn: " + str(args)) p = os.fork() if p == 0: os.spawnve(os.P_NOWAIT, path, args, env) @@ -50,8 +51,10 @@ class VfbifController(DevController): # is HVM, so qemu-dm will handle the vfb. return - std_args = [ "--domid", "%d" % self.vm.getDomid(), - "--title", self.vm.getName() ] + args = [ xen.util.auxbin.pathTo("qemu-dm"), + "-M", "xenpv", + "-d", "%d" % self.vm.getDomid(), + "-domain-name", self.vm.getName() ] t = config.get("type", None) if t == "vnc": passwd = None @@ -65,15 +68,14 @@ class VfbifController(DevController): else: log.debug("No VNC passwd configured for vfb access") - # Try to start the vnc backend - args = [xen.util.auxbin.pathTo("xen-vncfb")] - if config.has_key("vncunused"): - args += ["--unused"] - elif config.has_key("vncdisplay"): - args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))] - vnclisten = config.get("vnclisten", + vnclisten = config.get('vnclisten', xen.xend.XendOptions.instance().get_vnclisten_address()) - args += [ "--listen", vnclisten ] + vncdisplay = config.get('vncdisplay', 0) + args += ['-vnc', "%s:%d" % (vnclisten, int(vncdisplay))] + + if config.get('vncunused', 0): + args += ['-vncunused'] + if config.has_key("keymap"): args += ["-k", "%s" % config["keymap"]] else: @@ -81,7 +83,7 @@ class VfbifController(DevController): if xoptions.get_keymap(): args += ["-k", "%s" % xoptions.get_keymap()] - spawn_detached(args[0], args + std_args, os.environ) + spawn_detached(args[0], args, os.environ) elif t == "sdl": args = [xen.util.auxbin.pathTo("xen-sdlfb")] env = dict(os.environ) @@ -89,7 +91,7 @@ class VfbifController(DevController): env['DISPLAY'] = config["display"] if config.has_key("xauthority"): env['XAUTHORITY'] = config["xauthority"] - spawn_detached(args[0], args + std_args, env) + spawn_detached(args[0], args, env) else: raise VmError('Unknown vfb type %s (%s)' % (t, repr(config))) diff -rupN xen-3.1.2-src.orig/tools/xenfb/xenfb.c xen-3.1.2-src.new/tools/xenfb/xenfb.c --- xen-3.1.2-src.orig/tools/xenfb/xenfb.c 2007-11-14 18:35:27.000000000 -0500 +++ xen-3.1.2-src.new/tools/xenfb/xenfb.c 2007-12-01 14:49:01.000000000 -0500 @@ -677,37 +677,58 @@ static int xenfb_on_state_change(struct return 0; } -/* Returns 0 normally, -1 on error, or -2 if the domain went away. */ -int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds) +int xenfb_dispatch_channel(struct xenfb *xenfb_pub) { struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; evtchn_port_t port; + port = xc_evtchn_pending(xenfb->evt_xch); + if (port == -1) + return -1; + + if (port == xenfb->fb.port) + xenfb_on_fb_event(xenfb); + else if (port == xenfb->kbd.port) + xenfb_on_kbd_event(xenfb); + + if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) + return -1; + + return 0; +} + +int xenfb_dispatch_store(struct xenfb *xenfb_pub) +{ + struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; unsigned dummy; char **vec; int r; - if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) { - port = xc_evtchn_pending(xenfb->evt_xch); - if (port == -1) - return -1; - - if (port == xenfb->fb.port) - xenfb_on_fb_event(xenfb); - else if (port == xenfb->kbd.port) - xenfb_on_kbd_event(xenfb); + vec = xs_read_watch(xenfb->xsh, &dummy); + free(vec); + r = xenfb_on_state_change(&xenfb->fb); + if (r == 0) + r = xenfb_on_state_change(&xenfb->kbd); + if (r == -1) + return -2; + + return 0; +} - if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) - return -1; + +/* Returns 0 normally, -1 on error, or -2 if the domain went away. */ +int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds) +{ + struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; + int ret; + + if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) { + if ((ret = xenfb_dispatch_channel(xenfb_pub)) < 0) + return ret; } if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) { - vec = xs_read_watch(xenfb->xsh, &dummy); - free(vec); - r = xenfb_on_state_change(&xenfb->fb); - if (r == 0) - r = xenfb_on_state_change(&xenfb->kbd); - if (r == -1) - return -2; + if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0) + return ret; } return 0; @@ -724,6 +745,18 @@ int xenfb_select_fds(struct xenfb *xenfb return fd1 > fd2 ? fd1 + 1 : fd2 + 1; } +int xenfb_get_store_fd(struct xenfb *xenfb_pub) +{ + struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; + return xs_fileno(xenfb->xsh); +} + +int xenfb_get_channel_fd(struct xenfb *xenfb_pub) +{ + struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; + return xc_evtchn_fd(xenfb->evt_xch); +} + static int xenfb_kbd_event(struct xenfb_private *xenfb, union xenkbd_in_event *event) { @@ -784,3 +817,10 @@ int xenfb_send_position(struct xenfb *xe return xenfb_kbd_event(xenfb, &event); } +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -rupN xen-3.1.2-src.orig/tools/xenfb/xenfb.h xen-3.1.2-src.new/tools/xenfb/xenfb.h --- xen-3.1.2-src.orig/tools/xenfb/xenfb.h 2007-11-14 18:35:27.000000000 -0500 +++ xen-3.1.2-src.new/tools/xenfb/xenfb.h 2007-12-01 14:49:01.000000000 -0500 @@ -25,8 +25,12 @@ void xenfb_teardown(struct xenfb *xenfb) int xenfb_attach_dom(struct xenfb *xenfb, int domid); +int xenfb_dispatch_store(struct xenfb *xenfb_pub); +int xenfb_dispatch_channel(struct xenfb *xenfb_pub); int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds); int xenfb_poll(struct xenfb *xenfb, fd_set *readfds); +int xenfb_get_store_fd(struct xenfb *xenfb_pub); +int xenfb_get_channel_fd(struct xenfb *xenfb_pub); int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode); int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);