bimodal pvfb backend: Deal with both 32 and 64 bit frontends.

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
This commit is contained in:
kfraser@localhost.localdomain committed 2007-01-23 14:57:01 +00:00
1 parent 7606be28a6
commit 7bd46b4635
1 file changed
+87 -11
+87 -11
View File
@@ -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,36 +326,107 @@ static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
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
* 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_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;
}
if (xenfb->pub.pixels == NULL)
goto out;
return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
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_device *dev)
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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.