[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] bimodal pvfb backend: Deal with both 32 and 64 bit frontends.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1169564221 0
# Node ID d54c8dab1e64719e158d734c522b902afde0fcfd
# Parent  c545932a18f33b27e5c889e6e51759b23bd08f12
bimodal pvfb backend: Deal with both 32 and 64 bit frontends.

Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxx>
---
 tools/xenfb/xenfb.c |  100 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 88 insertions(+), 12 deletions(-)

diff -r c545932a18f3 -r d54c8dab1e64 tools/xenfb/xenfb.c
--- a/tools/xenfb/xenfb.c       Tue Jan 23 14:48:42 2007 +0000
+++ b/tools/xenfb/xenfb.c       Tue Jan 23 14:57:01 2007 +0000
@@ -7,6 +7,7 @@
 #include <xen/io/xenbus.h>
 #include <xen/io/fbif.h>
 #include <xen/io/kbdif.h>
+#include <xen/io/protocols.h>
 #include <sys/select.h>
 #include <stdbool.h>
 #include <xen/linux/evtchn.h>
@@ -40,6 +41,7 @@ struct xenfb_private {
        struct xs_handle *xsh;  /* xs daemon handle */
        struct xenfb_device fb, kbd;
        size_t fb_len;          /* size of framebuffer */
+       char protocol[64];      /* frontend protocol */
 };
 
 static void xenfb_detach_dom(struct xenfb_private *);
@@ -324,16 +326,79 @@ static int xenfb_wait_for_frontend_initi
        return 0;
 }
 
+static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
+{
+       uint32_t *src32 = src;
+       uint64_t *src64 = src;
+       int i;
+
+       for (i = 0; i < count; i++)
+               dst[i] = (mode == 32) ? src32[i] : src64[i];
+}
+
 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;
+       unsigned long *pgmfns = NULL;
+       unsigned long *fbmfns = NULL;
+       void *map, *pd;
+       int mode, ret = -1;
+
+       /* default to native */
+       pd = page->pd;
+       mode = sizeof(unsigned long) * 8;
+
+       if (0 == strlen(xenfb->protocol)) {
+               /*
+                * Undefined protocol, some guesswork needed.
+                *
+                * Old frontends which don't set the protocol use
+                * one page directory only, thus pd[1] must be zero.
+                * pd[1] of the 32bit struct layout and the lower
+                * 32 bits of pd[0] of the 64bit struct layout have
+                * the same location, so we can check that ...
+                */
+               uint32_t *ptr32 = NULL;
+               uint32_t *ptr64 = NULL;
+#if defined(__i386_)
+               ptr32 = page->pd;
+               ptr64 = ((void*)page->pd) + 4;
+#elif defined(__x86_64__)
+               ptr32 = ((void*)page->pd) - 4;
+               ptr64 = page->pd;
+#endif
+               if (ptr32) {
+                       if (0 == ptr32[1]) {
+                               mode = 32;
+                               pd   = ptr32;
+                       } else {
+                               mode = 64;
+                               pd   = ptr64;
+                       }
+               }
+#if defined(__x86_64__)
+       } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
+               /* 64bit dom0, 32bit domU */
+               mode = 32;
+               pd   = ((void*)page->pd) - 4;
+#elif defined(__i386_)
+       } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
+               /* 32bit dom0, 64bit domU */
+               mode = 64;
+               pd   = ((void*)page->pd) + 4;
+#endif
+       }
 
        n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
-       n_fbdirs = n_fbmfns * sizeof(unsigned long);
+       n_fbdirs = n_fbmfns * mode / 8;
        n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+
+       pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
+       fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
+       if (!pgmfns || !fbmfns)
+               goto out;
 
        /*
         * Bug alert: xc_map_foreign_batch() can fail partly and
@@ -341,19 +406,27 @@ static int xenfb_map_fb(struct xenfb_pri
         * 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_copy_mfns(mode, n_fbdirs, pgmfns, pd);
+       map = xc_map_foreign_batch(xenfb->xc, domid,
+                                  PROT_READ, pgmfns, n_fbdirs);
+       if (map == NULL)
+               goto out;
+       xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
+       munmap(map, n_fbdirs * XC_PAGE_SIZE);
 
        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);
+       if (xenfb->pub.pixels == NULL)
+               goto out;
+
+       ret = 0; /* all is fine */
+
+ out:
+       if (pgmfns)
+               free(pgmfns);
+       if (fbmfns)
+               free(fbmfns);
+       return ret;
 }
 
 static int xenfb_bind(struct xenfb_device *dev)
@@ -368,6 +441,9 @@ static int xenfb_bind(struct xenfb_devic
        if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
                            &evtchn) < 0)
                return -1;
+       if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "protocol", "%63s",
+                           xenfb->protocol) < 0)
+               xenfb->protocol[0] = '\0';
 
        dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
                                               dev->otherend_id, evtchn);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.