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);