# 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
|