From d00c194e884a17ac06b02485c36137ca2b0e1a45 Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Jan 23 2007 17:35:26 +0000 Subject: Added PVFB back-compat support to make FC5/6 guest kernels work --- diff --git a/xen-pvfb-compat.patch b/xen-pvfb-compat.patch new file mode 100644 index 0000000..126de34 --- /dev/null +++ b/xen-pvfb-compat.patch @@ -0,0 +1,1044 @@ +diff -r a2618d3912e7 tools/python/xen/xend/server/vfbif.py +--- a/tools/python/xen/xend/server/vfbif.py Mon Dec 04 19:13:55 2006 +0000 ++++ b/tools/python/xen/xend/server/vfbif.py Tue Dec 05 10:29:17 2006 +0100 +@@ -37,5 +37,8 @@ class VfbifController(DevController): + def createDevice(self, config): + DevController.createDevice(self, config) ++ # old frontend compatibility ++ self.vm._writeDom("console/use_graphics", "1") ++ # /old + std_args = [ "--domid", "%d" % self.vm.getDomid(), + "--title", self.vm.getName() ] + t = config.get("type", None) +diff -r 7df4d8cfba3b tools/python/xen/xm/create.py +--- a/tools/python/xen/xm/create.py Tue Dec 05 12:42:29 2006 +0000 ++++ b/tools/python/xen/xm/create.py Thu Dec 07 15:50:07 2006 +0100 +@@ -577,6 +577,24 @@ def configure_usb(config_devs, vals): + config_devs.append(['device', config_usb]) + + def configure_vfbs(config_devs, vals): ++ # old config compatibility ++ if vals.vfb == [] and (vals.sdl or vals.vnc): ++ if vals.vnc: ++ cfg = 'type=vnc' ++ if vals.vncdisplay: ++ cfg += ',vncdisplay=%s' % vals.vncdisplay ++ if vals.vncunused: ++ cfg += ',vncunused=%s' % vals.vncunused ++ if vals.vnclisten: ++ cfg += ',vnclisten=%s' % vals.vnclisten ++ else: ++ cfg = 'type=sdl' ++ if vals.xauthority: ++ cfg += ',xauthority=%s' % vals.xauthority ++ if vals.display: ++ cfg += ',display=%s' % vals.display ++ vals.vfb = [ cfg, ] ++ # /old + for f in vals.vfb: + d = comma_sep_kv_to_dict(f) + config = ['vfb'] +diff -r a2618d3912e7 tools/xenfb/Makefile +--- a/tools/xenfb/Makefile Mon Dec 04 19:13:55 2006 +0000 ++++ b/tools/xenfb/Makefile Tue Dec 05 10:26:52 2006 +0100 +@@ -13,12 +17,14 @@ all: build + + .PHONY: build + build: mk-symlinks +- $(MAKE) vncfb sdlfb ++ $(MAKE) vncfb sdlfb vncfbo sdlfbo + + install: all + $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)/xen/bin + $(INSTALL_PROG) vncfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfb + $(INSTALL_PROG) sdlfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfb ++ $(INSTALL_PROG) vncfbo $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfbo ++ $(INSTALL_PROG) sdlfbo $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfbo + + sdlfb: sdlfb.o xenfb.o + +@@ -33,3 +39,14 @@ vncfb: LDLIBS += $(shell libvncserver-co + vncfb: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore + + sdlfb.o xenfb.o vncfb.o: xenfb.h ++ ++sdlfbo vncfbo: ++ $(CC) $(LDFLAGS) -o $@ $^ $(LOADLIBES) $(LDLIBS) ++ ++sdlfbo: sdlfb.o oldxenfb.o ++sdlfbo: LDLIBS += $(shell sdl-config --libs) -lxenctrl -lxenstore ++ ++vncfbo: vncfb.o oldxenfb.o ++vncfbo: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore ++ ++oldxenfb.o: xenfb.h oldxenfb.h oldxenkbd.h +diff -r a2618d3912e7 tools/xenfb/sdlfb.c +--- a/tools/xenfb/sdlfb.c Tue Dec 05 12:42:29 2006 +0000 ++++ b/tools/xenfb/sdlfb.c Thu Dec 07 19:45:51 2006 +0100 +@@ -212,6 +212,7 @@ int main(int argc, char **argv) + struct xenfb *xenfb; + int domid = -1; + char * title = NULL; ++ int ret; + fd_set readfds; + int nfds; + struct SDLFBData data; +@@ -256,11 +257,19 @@ int main(int argc, char **argv) + exit(1); + } + +- if (xenfb_attach_dom(xenfb, domid) < 0) { ++ ret = xenfb_attach_dom(xenfb, domid); ++ if (ret < 0) { + fprintf(stderr, "Could not connect to domain (%s)\n", + strerror(errno)); + exit(1); + } ++ if (ret > 0) { ++ if (xenfb_switch_to_old_protocol(argv) < 0) { ++ fprintf(stderr, "Could not switch to old protocol (%s)\n", ++ strerror(errno)); ++ exit(1); ++ } ++ } + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Could not initialize SDL\n"); +diff -r a2618d3912e7 tools/xenfb/vncfb.c +--- a/tools/xenfb/vncfb.c Mon Dec 04 19:13:55 2006 +0000 ++++ b/tools/xenfb/vncfb.c Tue Dec 05 10:26:52 2006 +0100 +@@ -269,6 +269,7 @@ int main(int argc, char **argv) + bool unused = false; + int opt; + struct xenfb *xenfb; ++ int ret; + fd_set readfds; + int nfds; + char portstr[10]; +@@ -340,10 +341,18 @@ int main(int argc, char **argv) + exit(1); + } + +- if (xenfb_attach_dom(xenfb, domid) < 0) { ++ ret = xenfb_attach_dom(xenfb, domid); ++ if (ret < 0) { + fprintf(stderr, "Could not connect to domain (%s)\n", + strerror(errno)); + exit(1); ++ } ++ if (ret > 0) { ++ if (xenfb_switch_to_old_protocol(argv) < 0) { ++ fprintf(stderr, "Could not switch to old protocol (%s)\n", ++ strerror(errno)); ++ exit(1); ++ } + } + + server = rfbGetScreen(&fake_argc, fake_argv, +diff -r a2618d3912e7 tools/xenfb/xenfb.c +--- a/tools/xenfb/xenfb.c Mon Dec 04 19:13:55 2006 +0000 ++++ b/tools/xenfb/xenfb.c Tue Dec 05 10:26:52 2006 +0100 +@@ -290,6 +301,60 @@ static int xenfb_hotplug(struct xenfb_de + return 0; + } + ++static int xenfb_using_old_protocol(struct xenfb_private *xenfb) ++{ ++ struct xs_handle *xsh = xenfb->xsh; ++ char buf[64]; ++ char *p, *v, **vec; ++ enum xenbus_state state; ++ unsigned dummy; ++ int ret; ++ ++ p = xenfb_path_in_dom(xsh, buf, sizeof(buf), ++ xenfb->fb.otherend_id, "vfb/page-ref"); ++ if (!xs_watch(xsh, p, "")) ++ return -1; ++ ++ for (;;) { ++ state = xenfb_read_state(xsh, xenfb->fb.otherend); ++ if (state > XenbusStateInitialising) { ++ ret = 0; /* frontend talks xenbus protocol */ ++ break; ++ } ++ ++ v = xs_read(xsh, XBT_NULL, p, NULL); ++ free(v); ++ if (v) { ++ ret = 1; /* frontend talks old protocol */ ++ break; ++ } ++ ++ vec = xs_read_watch(xsh, &dummy); ++ if (!vec) { ++ ret = -1; ++ break; ++ } ++ free(vec); ++ } ++ ++ xs_unwatch(xsh, p, ""); ++ return ret; ++} ++ ++int xenfb_switch_to_old_protocol(char **argv) ++{ ++ size_t len = strlen(argv[0]); ++ char *prog; ++ ++ prog = malloc(len + 2); ++ if (!prog) ++ return -1; ++ strcpy(prog, argv[0]); ++ strcpy(prog + len, "o"); ++ argv[0] = prog; ++ return execv(prog, argv); ++} ++ + static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev) + { + switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend, +@@ -473,6 +534,9 @@ int xenfb_attach_dom(struct xenfb *xenfb + goto error; + if (!xs_watch(xsh, xenfb->kbd.otherend, "")) + goto error; ++ ++ if (xenfb_using_old_protocol(xenfb)) ++ return 1; + + if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0) + goto error; +diff -r a2618d3912e7 tools/xenfb/xenfb.h +--- a/tools/xenfb/xenfb.h Mon Dec 04 19:13:55 2006 +0000 ++++ b/tools/xenfb/xenfb.h Tue Dec 05 10:26:52 2006 +0100 +@@ -32,4 +32,6 @@ int xenfb_send_motion(struct xenfb *xenf + int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y); + int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y); + ++int xenfb_switch_to_old_protocol(char **); ++ + #endif +diff -r 3f0ca90351e2 tools/xenfb/oldxenfb.c +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/tools/xenfb/oldxenfb.c Fri Dec 08 16:31:34 2006 +0100 +@@ -0,0 +1,611 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "oldxenfb.h" ++#include "oldxenkbd.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xenfb.h" ++ ++// FIXME defend against malicious frontend? ++ ++struct xenfb_device { ++ const char *devicetype; ++ char nodename[64]; /* backend xenstore dir */ ++ char otherend[64]; /* frontend xenstore dir */ ++ int otherend_id; /* frontend domid */ ++ enum xenbus_state state; /* backend state */ ++ void *page; /* shared page */ ++ evtchn_port_t port; ++ struct xenfb_private *xenfb; ++}; ++ ++struct xenfb_private { ++ struct xenfb pub; ++ int evt_xch; /* event channel driver handle */ ++ int xc; /* hypervisor interface handle */ ++ struct xs_handle *xsh; /* xs daemon handle */ ++ struct xenfb_device fb, kbd; ++ size_t fb_len; /* size of framebuffer */ ++}; ++ ++static void xenfb_detach_dom(struct xenfb_private *); ++static int xenfb_fb_event(struct xenfb_private *, union xenfb_in_event *); ++ ++static char *xenfb_path_in_dom(struct xs_handle *xsh, ++ char *buf, size_t size, ++ unsigned domid, const char *fmt, ...) ++{ ++ va_list ap; ++ char *domp = xs_get_domain_path(xsh, domid); ++ int n; ++ ++ if (domp == NULL) ++ return NULL; ++ ++ n = snprintf(buf, size, "%s/", domp); ++ free(domp); ++ if (n >= size) ++ return NULL; ++ ++ va_start(ap, fmt); ++ n += vsnprintf(buf + n, size - n, fmt, ap); ++ va_end(ap); ++ if (n >= size) ++ return NULL; ++ ++ return buf; ++} ++ ++static int xenfb_xs_scanf1(struct xs_handle *xsh, ++ const char *dir, const char *node, ++ const char *fmt, void *dest) ++{ ++ char buf[1024]; ++ char *p; ++ int ret; ++ ++ if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) { ++ errno = ENOENT; ++ return -1; ++ } ++ p = xs_read(xsh, XBT_NULL, buf, NULL); ++ if (!p) { ++ errno = ENOENT; ++ return -1; ++ } ++ ret = sscanf(p, fmt, dest); ++ free(p); ++ if (ret != 1) { ++ errno = EDOM; ++ return -1; ++ } ++ return ret; ++} ++ ++static int xenfb_xs_printf(struct xs_handle *xsh, ++ const char *dir, const char *node, char *fmt, ...) ++{ ++ va_list ap; ++ char key[1024]; ++ char val[1024]; ++ int n; ++ ++ if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) { ++ errno = ENOENT; ++ return -1; ++ } ++ ++ va_start(ap, fmt); ++ n = vsnprintf(val, sizeof(val), fmt, ap); ++ va_end(ap); ++ if (n >= sizeof(val)) { ++ errno = ENOSPC; /* close enough */ ++ return -1; ++ } ++ ++ if (!xs_write(xsh, XBT_NULL, key, val, n)) ++ return -1; ++ return 0; ++} ++ ++static void xenfb_device_init(struct xenfb_device *dev, ++ const char *type, ++ struct xenfb_private *xenfb) ++{ ++ dev->devicetype = type; ++ dev->otherend_id = -1; ++ dev->port = -1; ++ dev->xenfb = xenfb; ++} ++ ++int xenfb_device_set_domain(struct xenfb_device *dev, int domid) ++{ ++ struct xenfb_private *xenfb = dev->xenfb; ++ ++ dev->otherend_id = domid; ++ ++ if (!xenfb_path_in_dom(xenfb->xsh, ++ dev->otherend, sizeof(dev->otherend), ++ domid, "device/%s/0", dev->devicetype)) { ++ errno = ENOENT; ++ return -1; ++ } ++ if (!xenfb_path_in_dom(xenfb->xsh, ++ dev->nodename, sizeof(dev->nodename), ++ 0, "backend/%s/%d/0", dev->devicetype, domid)) { ++ errno = ENOENT; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++struct xenfb *xenfb_new(void) ++{ ++ struct xenfb_private *xenfb = malloc(sizeof(*xenfb)); ++ int serrno; ++ ++ if (xenfb == NULL) ++ return NULL; ++ ++ memset(xenfb, 0, sizeof(*xenfb)); ++ xenfb->evt_xch = xenfb->xc = -1; ++ xenfb_device_init(&xenfb->fb, "vfb", xenfb); ++ xenfb_device_init(&xenfb->kbd, "vkbd", xenfb); ++ ++ xenfb->evt_xch = xc_evtchn_open(); ++ if (xenfb->evt_xch == -1) ++ goto fail; ++ ++ xenfb->xc = xc_interface_open(); ++ if (xenfb->xc == -1) ++ goto fail; ++ ++ xenfb->xsh = xs_daemon_open(); ++ if (!xenfb->xsh) ++ goto fail; ++ ++ return &xenfb->pub; ++ ++ fail: ++ serrno = errno; ++ xenfb_delete(&xenfb->pub); ++ errno = serrno; ++ return NULL; ++} ++ ++/* Remove the backend area in xenbus since the framebuffer really is ++ going away. */ ++void xenfb_teardown(struct xenfb *xenfb_pub) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ ++ xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename); ++ xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename); ++} ++ ++ ++void xenfb_delete(struct xenfb *xenfb_pub) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ ++ xenfb_detach_dom(xenfb); ++ if (xenfb->xc >= 0) ++ xc_interface_close(xenfb->xc); ++ if (xenfb->evt_xch >= 0) ++ xc_evtchn_close(xenfb->evt_xch); ++ if (xenfb->xsh) ++ xs_daemon_close(xenfb->xsh); ++ free(xenfb); ++} ++ ++static enum xenbus_state xenfb_read_state(struct xs_handle *xsh, ++ const char *dir) ++{ ++ int ret, state; ++ ++ ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state); ++ if (ret < 0) ++ return XenbusStateUnknown; ++ ++ if ((unsigned)state > XenbusStateClosed) ++ state = XenbusStateUnknown; ++ return state; ++} ++ ++static int xenfb_switch_state(struct xenfb_device *dev, ++ enum xenbus_state state) ++{ ++ struct xs_handle *xsh = dev->xenfb->xsh; ++ ++ if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0) ++ return -1; ++ dev->state = state; ++ return 0; ++} ++ ++int xenfb_switch_to_old_protocol(char **argv) ++{ ++ abort(); ++} ++ ++static int xenfb_map_fb(struct xenfb_private *xenfb, int domid) ++{ ++ struct xenfb_page *page = xenfb->fb.page; ++ int n_fbmfns; ++ int n_fbdirs; ++ unsigned long *fbmfns; ++ ++ n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; ++ n_fbdirs = n_fbmfns * sizeof(unsigned long); ++ n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; ++ ++ /* ++ * Bug alert: xc_map_foreign_batch() can fail partly and ++ * return a non-null value. This is a design flaw. When it ++ * happens, we happily continue here, and later crash on ++ * access. ++ */ ++ fbmfns = xc_map_foreign_batch(xenfb->xc, domid, ++ PROT_READ, page->pd, n_fbdirs); ++ if (fbmfns == NULL) ++ return -1; ++ ++ xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid, ++ PROT_READ | PROT_WRITE, fbmfns, n_fbmfns); ++ if (xenfb->pub.pixels == NULL) { ++ munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE); ++ return -1; ++ } ++ ++ return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE); ++} ++ ++static int xenfb_bind(struct xenfb_device *dev) ++{ ++ struct xenfb_private *xenfb = dev->xenfb; ++ unsigned long mfn; ++ evtchn_port_t evtchn; ++ char buf[64]; ++ char *p, **vec; ++ unsigned dummy; ++ ++ p = xenfb_path_in_dom(xenfb->xsh, buf, sizeof(buf), ++ dev->otherend_id, dev->devicetype); ++ if (!xs_watch(xenfb->xsh, p, "")) ++ return -1; ++ for (;;) { ++ if (xenfb_xs_scanf1(xenfb->xsh, p, "page-ref", "%lu", ++ &mfn) < 0) { ++ if (errno == ENOENT || errno == EAGAIN) ++ goto wait; ++ return -1; ++ } ++ if (xenfb_xs_scanf1(xenfb->xsh, p, "event-channel", "%u", ++ &evtchn) < 0) { ++ if (errno == ENOENT || errno == EAGAIN) ++ goto wait; ++ return -1; ++ } ++ break; ++ ++ wait: ++ printf("Waiting...\n"); ++ vec = xs_read_watch(xenfb->xsh, &dummy); ++ if (!vec) ++ return -1; ++ free(vec); ++ } ++ ++ dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch, ++ dev->otherend_id, evtchn); ++ if (dev->port == -1) ++ return -1; ++ ++ dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id, ++ XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn); ++ if (dev->page == NULL) ++ return -1; ++ ++ return 0; ++} ++ ++static void xenfb_unbind(struct xenfb_device *dev) ++{ ++ if (dev->page) { ++ munmap(dev->page, XC_PAGE_SIZE); ++ dev->page = NULL; ++ } ++ if (dev->port >= 0) { ++ xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port); ++ dev->port = -1; ++ } ++} ++ ++static void xenfb_dev_fatal(struct xenfb_device *dev, int err, ++ const char *fmt, ...) ++{ ++ struct xs_handle *xsh = dev->xenfb->xsh; ++ va_list ap; ++ char errdir[80]; ++ char buf[1024]; ++ int n; ++ ++ fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */ ++ va_start(ap, fmt); ++ vfprintf(stderr, fmt, ap); ++ va_end(ap); ++ if (err) ++ fprintf(stderr, " (%s)", strerror(err)); ++ putc('\n', stderr); ++ ++ if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0, ++ "error/%s", dev->nodename)) ++ goto out; /* FIXME complain */ ++ ++ va_start(ap, fmt); ++ n = snprintf(buf, sizeof(buf), "%d ", err); ++ snprintf(buf + n, sizeof(buf) - n, fmt, ap); ++ va_end(ap); ++ ++ if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0) ++ goto out; /* FIXME complain */ ++ ++ out: ++ xenfb_switch_state(dev, XenbusStateClosing); ++} ++ ++int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ struct xs_handle *xsh = xenfb->xsh; ++ int val, serrno; ++ struct xenfb_page *fb_page; ++ union xenfb_in_event event; ++ ++ xenfb_detach_dom(xenfb); ++ ++ xenfb_device_set_domain(&xenfb->fb, domid); ++ xenfb_device_set_domain(&xenfb->kbd, domid); ++ ++ if (!xs_watch(xsh, xenfb->fb.otherend, "")) ++ goto error; ++ if (!xs_watch(xsh, xenfb->kbd.otherend, "")) ++ goto error; ++ ++ if (xenfb_bind(&xenfb->fb) < 0) ++ goto error; ++ if (xenfb_bind(&xenfb->kbd) < 0) ++ goto error; ++ ++ /* TODO check for permitted ranges */ ++ fb_page = xenfb->fb.page; ++ xenfb->pub.depth = fb_page->depth; ++ xenfb->pub.width = fb_page->width; ++ xenfb->pub.height = fb_page->height; ++ /* TODO check for consistency with the above */ ++ xenfb->fb_len = fb_page->mem_length; ++ xenfb->pub.row_stride = fb_page->line_length; ++ ++ if (xenfb_map_fb(xenfb, domid) < 0) ++ goto error; ++ ++ event.type = XENFB_TYPE_SET_EVENTS; ++ event.set_events.flags = XENFB_FLAG_UPDATE; ++ if (xenfb_fb_event(xenfb, &event)) ++ goto error; ++ ++ return 0; ++ ++ error: ++ serrno = errno; ++ xenfb_detach_dom(xenfb); ++ xenfb_dev_fatal(&xenfb->fb, serrno, "on fire"); ++ xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire"); ++ errno = serrno; ++ return -1; ++} ++ ++static void xenfb_detach_dom(struct xenfb_private *xenfb) ++{ ++ xenfb_unbind(&xenfb->fb); ++ xenfb_unbind(&xenfb->kbd); ++ if (xenfb->pub.pixels) { ++ munmap(xenfb->pub.pixels, xenfb->fb_len); ++ xenfb->pub.pixels = NULL; ++ } ++} ++ ++static void xenfb_on_fb_event(struct xenfb_private *xenfb) ++{ ++ uint32_t prod, cons; ++ struct xenfb_page *page = xenfb->fb.page; ++ ++ prod = page->out_prod; ++ if (prod == page->out_cons) ++ return; ++ rmb(); /* ensure we see ring contents up to prod */ ++ for (cons = page->out_cons; cons != prod; cons++) { ++ union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); ++ ++ switch (event->type) { ++ case XENFB_TYPE_UPDATE: ++ if (xenfb->pub.update) ++ xenfb->pub.update(&xenfb->pub, ++ event->update.x, event->update.y, ++ event->update.width, event->update.height); ++ break; ++ } ++ } ++ mb(); /* ensure we're done with ring contents */ ++ page->out_cons = cons; ++ xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); ++} ++ ++static void xenfb_on_kbd_event(struct xenfb_private *xenfb) ++{ ++ struct xenkbd_info *page = xenfb->kbd.page; ++ ++ /* We don't understand any keyboard events, so just ignore them. */ ++ if (page->out_prod == page->out_cons) ++ return; ++ page->out_cons = page->out_prod; ++ xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port); ++} ++ ++static int xenfb_on_state_change(struct xenfb_device *dev) ++{ ++ enum xenbus_state state; ++ ++ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend); ++ ++ switch (state) { ++ case XenbusStateUnknown: ++ /* There was an error reading the frontend state. The ++ domain has probably gone away; in any case, there's ++ not much point in us continuing. */ ++ return -1; ++ case XenbusStateInitialising: ++ case XenbusStateInitWait: ++ case XenbusStateInitialised: ++ case XenbusStateConnected: ++ break; ++ case XenbusStateClosing: ++ xenfb_unbind(dev); ++ xenfb_switch_state(dev, state); ++ break; ++ case XenbusStateClosed: ++ xenfb_switch_state(dev, state); ++ } ++ 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) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ evtchn_port_t port; ++ 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); ++ ++ if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) ++ return -1; ++ } ++ ++ 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; ++ } ++ ++ return 0; ++} ++ ++int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ int fd1 = xc_evtchn_fd(xenfb->evt_xch); ++ int fd2 = xs_fileno(xenfb->xsh); ++ ++ FD_SET(fd1, readfds); ++ FD_SET(fd2, readfds); ++ return fd1 > fd2 ? fd1 + 1 : fd2 + 1; ++} ++ ++static int xenfb_fb_event(struct xenfb_private *xenfb, ++ union xenfb_in_event *event) ++{ ++ uint32_t prod; ++ struct xenfb_page *page = xenfb->fb.page; ++ ++ prod = page->in_prod; ++ if (prod - page->in_cons == XENFB_IN_RING_LEN) { ++ errno = EAGAIN; ++ return -1; ++ } ++ ++ mb(); /* ensure ring space available */ ++ XENFB_IN_RING_REF(page, prod) = *event; ++ wmb(); /* ensure ring contents visible */ ++ page->in_prod = prod + 1; ++ return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); ++} ++ ++static int xenfb_kbd_event(struct xenfb_private *xenfb, ++ union xenkbd_in_event *event) ++{ ++ uint32_t prod; ++ struct xenkbd_info *page = xenfb->kbd.page; ++ ++ prod = page->in_prod; ++ if (prod - page->in_cons == XENKBD_IN_RING_LEN) { ++ errno = EAGAIN; ++ return -1; ++ } ++ ++ mb(); /* ensure ring space available */ ++ XENKBD_IN_RING_REF(page, prod) = *event; ++ wmb(); /* ensure ring contents visible */ ++ page->in_prod = prod + 1; ++ return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port); ++} ++ ++int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ union xenkbd_in_event event; ++ ++ memset(&event, 0, XENKBD_IN_EVENT_SIZE); ++ event.type = XENKBD_TYPE_KEY; ++ event.key.pressed = down ? 1 : 0; ++ event.key.keycode = keycode; ++ ++ return xenfb_kbd_event(xenfb, &event); ++} ++ ++int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y) ++{ ++ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub; ++ union xenkbd_in_event event; ++ ++ memset(&event, 0, XENKBD_IN_EVENT_SIZE); ++ event.type = XENKBD_TYPE_MOTION; ++ event.motion.rel_x = rel_x; ++ event.motion.rel_y = rel_y; ++ ++ return xenfb_kbd_event(xenfb, &event); ++} ++ ++int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y) ++{ ++ abort(); ++} +diff -r 7df4d8cfba3b tools/xenfb/oldxenfb.h +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/tools/xenfb/oldxenfb.h Tue Dec 05 10:26:52 2006 +0100 +@@ -0,0 +1,108 @@ ++/* ++ * linux/include/linux/xenfb.h -- Xen virtual frame buffer device ++ * ++ * Copyright (C) 2005 ++ * ++ * Anthony Liguori ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#ifndef _LINUX_XENFB_H ++#define _LINUX_XENFB_H ++ ++#include ++ ++/* out events */ ++ ++#define XENFB_OUT_EVENT_SIZE 40 ++ ++#define XENFB_TYPE_MOTION 1 ++#define XENFB_TYPE_UPDATE 2 ++ ++struct xenfb_motion /* currently unused */ ++{ ++ __u8 type; /* XENFB_TYPE_MOTION */ ++ __u16 x; /* The new x coordinate */ ++ __u16 y; /* The new y coordinate */ ++}; ++ ++struct xenfb_update ++{ ++ __u8 type; /* XENFB_TYPE_UPDATE */ ++ __u16 x; /* source x */ ++ __u16 y; /* source y */ ++ __u16 width; /* rect width */ ++ __u16 height; /* rect height */ ++}; ++ ++union xenfb_out_event ++{ ++ __u8 type; ++ struct xenfb_motion motion; ++ struct xenfb_update update; ++ char _[XENFB_OUT_EVENT_SIZE]; ++}; ++ ++/* in events */ ++ ++#define XENFB_IN_EVENT_SIZE 40 ++ ++#define XENFB_TYPE_SET_EVENTS 1 ++ ++#define XENFB_FLAG_MOTION 1 ++#define XENFB_FLAG_UPDATE 2 ++#define XENFB_FLAG_COPY 4 ++#define XENFB_FLAG_FILL 8 ++ ++struct xenfb_set_events ++{ ++ __u8 type; /* XENFB_TYPE_SET_EVENTS */ ++ __u32 flags; /* combination of XENFB_FLAG_* */ ++}; ++ ++union xenfb_in_event ++{ ++ __u8 type; ++ struct xenfb_set_events set_events; ++ char _[XENFB_OUT_EVENT_SIZE]; ++}; ++ ++/* shared page */ ++ ++#define XENFB_IN_RING_SIZE 1024 ++#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE) ++#define XENFB_IN_RING_OFFS 1024 ++#define XENFB_IN_RING(page) \ ++ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS)) ++#define XENFB_IN_RING_REF(page, idx) \ ++ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN]) ++ ++#define XENFB_OUT_RING_SIZE 2048 ++#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE) ++#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE) ++#define XENFB_OUT_RING(page) \ ++ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS)) ++#define XENFB_OUT_RING_REF(page, idx) \ ++ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN]) ++ ++struct xenfb_page ++{ ++ __u16 width; /* the width of the framebuffer (in pixels) */ ++ __u16 height; /* the height of the framebuffer (in pixels) */ ++ __u32 line_length; /* the length of a row of pixels (in bytes) */ ++ __u32 mem_length; /* the length of the framebuffer (in bytes) */ ++ __u8 depth; /* the depth of a pixel (in bits) */ ++ ++ unsigned long pd[2]; /* FIXME rename to pgdir? */ ++ /* FIXME pd[1] unused at this time, shrink? */ ++ ++ __u32 in_cons, in_prod; ++ __u32 out_cons, out_prod; ++}; ++ ++void xenfb_resume(void); ++ ++#endif +diff -r 7df4d8cfba3b tools/xenfb/oldxenkbd.h +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/tools/xenfb/oldxenkbd.h Tue Dec 05 10:26:52 2006 +0100 +@@ -0,0 +1,92 @@ ++/* ++ * linux/include/linux/xenkbd.h -- Xen virtual keyboard/mouse ++ * ++ * Copyright (C) 2005 ++ * ++ * Anthony Liguori ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ */ ++ ++#ifndef _LINUX_XENKBD_H ++#define _LINUX_XENKBD_H ++ ++#include ++ ++/* in events */ ++ ++#define XENKBD_IN_EVENT_SIZE 40 ++ ++#define XENKBD_TYPE_MOTION 1 /* mouse movement event */ ++#define XENKBD_TYPE_BUTTON 2 /* mouse button event */ ++#define XENKBD_TYPE_KEY 3 /* keyboard event */ ++ ++struct xenkbd_motion ++{ ++ __u8 type; /* XENKBD_TYPE_MOTION */ ++ __s16 rel_x; /* relative X motion */ ++ __s16 rel_y; /* relative Y motion */ ++}; ++ ++struct xenkbd_button ++{ ++ __u8 type; /* XENKBD_TYPE_BUTTON */ ++ __u8 pressed; /* 1 if pressed; 0 otherwise */ ++ __u8 button; /* the button (0, 1, 2 is right, middle, left) */ ++}; ++ ++struct xenkbd_key ++{ ++ __u8 type; /* XENKBD_TYPE_KEY */ ++ __u8 pressed; /* 1 if pressed; 0 otherwise */ ++ __u16 keycode; /* KEY_* from linux/input.h */ ++}; ++ ++union xenkbd_in_event ++{ ++ __u8 type; ++ struct xenkbd_motion motion; ++ struct xenkbd_button button; ++ struct xenkbd_key key; ++ char _[XENKBD_IN_EVENT_SIZE]; ++}; ++ ++/* out events */ ++ ++#define XENKBD_OUT_EVENT_SIZE 40 ++ ++union xenkbd_out_event ++{ ++ __u8 type; ++ char _[XENKBD_OUT_EVENT_SIZE]; ++}; ++ ++/* shared page */ ++ ++#define XENKBD_IN_RING_SIZE 2048 ++#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE) ++#define XENKBD_IN_RING_OFFS 1024 ++#define XENKBD_IN_RING(page) \ ++ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS)) ++#define XENKBD_IN_RING_REF(page, idx) \ ++ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN]) ++ ++#define XENKBD_OUT_RING_SIZE 1024 ++#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE) ++#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE) ++#define XENKBD_OUT_RING(page) \ ++ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS)) ++#define XENKBD_OUT_RING_REF(page, idx) \ ++ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN]) ++ ++struct xenkbd_info ++{ ++ __u32 in_cons, in_prod; ++ __u32 out_cons, out_prod; ++}; ++ ++void xenkbd_resume(void); ++ ++#endif diff --git a/xen.spec b/xen.spec index f0b3c17..cbc4a9f 100644 --- a/xen.spec +++ b/xen.spec @@ -3,7 +3,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 3.0.4 -Release: 2%{dist} +Release: 3%{dist} Group: Development/Libraries License: GPL URL: http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html @@ -21,6 +21,10 @@ Patch100: xen-config-dom0-minmem.patch Patch102: xen-3.0.2-config-allow-unix-server.patch Patch103: xen-3.0.2-config-disable-reloc.patch +# Hack to support guest kernels using old PVFB protocol +# from FC5/6 days. Can kill off once FC6 is EOL'd +Patch150: xen-pvfb-compat.patch + Patch251: pygrub-manykernels.patch # libVNCserver patches @@ -96,6 +100,9 @@ virtual machines. %patch102 -p1 %patch103 -p1 +# pvfb compat +%patch150 -p1 + # upstream patches %patch251 -p1 @@ -216,7 +223,10 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.a %changelog -* Mon Jan 22 2007 Daniel P. Berrange - 3.0.4-2 +* Tue Jan 23 2007 Daniel Berrange - 3.0.4-3.fc7 +- Added PVFB back compat for FC5/6 guests + +* Mon Jan 22 2007 Daniel P. Berrange - 3.0.4-2.fc7 - Ensure the arch-x86 header files are included in xen-devel package - Bring back patch to move /var/xen/dump to /var/lib/xen/dump - Make /var/log/xen mode 0700