Blob Blame History Raw
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 <linux/input.h>
+
+/* 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);