direct-io.hg

changeset 13564:d54c8dab1e64

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

Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
author kfraser@localhost.localdomain
date Tue Jan 23 14:57:01 2007 +0000 (2007-01-23)
parents c545932a18f3
children 3071537af9d8
files tools/xenfb/xenfb.c
line diff
     1.1 --- a/tools/xenfb/xenfb.c	Tue Jan 23 14:48:42 2007 +0000
     1.2 +++ b/tools/xenfb/xenfb.c	Tue Jan 23 14:57:01 2007 +0000
     1.3 @@ -7,6 +7,7 @@
     1.4  #include <xen/io/xenbus.h>
     1.5  #include <xen/io/fbif.h>
     1.6  #include <xen/io/kbdif.h>
     1.7 +#include <xen/io/protocols.h>
     1.8  #include <sys/select.h>
     1.9  #include <stdbool.h>
    1.10  #include <xen/linux/evtchn.h>
    1.11 @@ -40,6 +41,7 @@ struct xenfb_private {
    1.12  	struct xs_handle *xsh;	/* xs daemon handle */
    1.13  	struct xenfb_device fb, kbd;
    1.14  	size_t fb_len;		/* size of framebuffer */
    1.15 +	char protocol[64];	/* frontend protocol */
    1.16  };
    1.17  
    1.18  static void xenfb_detach_dom(struct xenfb_private *);
    1.19 @@ -324,36 +326,107 @@ static int xenfb_wait_for_frontend_initi
    1.20  	return 0;
    1.21  }
    1.22  
    1.23 +static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
    1.24 +{
    1.25 +	uint32_t *src32 = src;
    1.26 +	uint64_t *src64 = src;
    1.27 +	int i;
    1.28 +
    1.29 +	for (i = 0; i < count; i++)
    1.30 +		dst[i] = (mode == 32) ? src32[i] : src64[i];
    1.31 +}
    1.32 +
    1.33  static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
    1.34  {
    1.35  	struct xenfb_page *page = xenfb->fb.page;
    1.36  	int n_fbmfns;
    1.37  	int n_fbdirs;
    1.38 -	unsigned long *fbmfns;
    1.39 +	unsigned long *pgmfns = NULL;
    1.40 +	unsigned long *fbmfns = NULL;
    1.41 +	void *map, *pd;
    1.42 +	int mode, ret = -1;
    1.43 +
    1.44 +	/* default to native */
    1.45 +	pd = page->pd;
    1.46 +	mode = sizeof(unsigned long) * 8;
    1.47 +
    1.48 +	if (0 == strlen(xenfb->protocol)) {
    1.49 +		/*
    1.50 +		 * Undefined protocol, some guesswork needed.
    1.51 +		 *
    1.52 +		 * Old frontends which don't set the protocol use
    1.53 +		 * one page directory only, thus pd[1] must be zero.
    1.54 +		 * pd[1] of the 32bit struct layout and the lower
    1.55 +		 * 32 bits of pd[0] of the 64bit struct layout have
    1.56 +		 * the same location, so we can check that ...
    1.57 +		 */
    1.58 +		uint32_t *ptr32 = NULL;
    1.59 +		uint32_t *ptr64 = NULL;
    1.60 +#if defined(__i386_)
    1.61 +		ptr32 = page->pd;
    1.62 +		ptr64 = ((void*)page->pd) + 4;
    1.63 +#elif defined(__x86_64__)
    1.64 +		ptr32 = ((void*)page->pd) - 4;
    1.65 +		ptr64 = page->pd;
    1.66 +#endif
    1.67 +		if (ptr32) {
    1.68 +			if (0 == ptr32[1]) {
    1.69 +				mode = 32;
    1.70 +				pd   = ptr32;
    1.71 +			} else {
    1.72 +				mode = 64;
    1.73 +				pd   = ptr64;
    1.74 +			}
    1.75 +		}
    1.76 +#if defined(__x86_64__)
    1.77 +	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
    1.78 +		/* 64bit dom0, 32bit domU */
    1.79 +		mode = 32;
    1.80 +		pd   = ((void*)page->pd) - 4;
    1.81 +#elif defined(__i386_)
    1.82 +	} else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
    1.83 +		/* 32bit dom0, 64bit domU */
    1.84 +		mode = 64;
    1.85 +		pd   = ((void*)page->pd) + 4;
    1.86 +#endif
    1.87 +	}
    1.88  
    1.89  	n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
    1.90 -	n_fbdirs = n_fbmfns * sizeof(unsigned long);
    1.91 +	n_fbdirs = n_fbmfns * mode / 8;
    1.92  	n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
    1.93  
    1.94 +	pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
    1.95 +	fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
    1.96 +	if (!pgmfns || !fbmfns)
    1.97 +		goto out;
    1.98 +
    1.99  	/*
   1.100  	 * Bug alert: xc_map_foreign_batch() can fail partly and
   1.101  	 * return a non-null value.  This is a design flaw.  When it
   1.102  	 * happens, we happily continue here, and later crash on
   1.103  	 * access.
   1.104  	 */
   1.105 -	fbmfns = xc_map_foreign_batch(xenfb->xc, domid,
   1.106 -			PROT_READ, page->pd, n_fbdirs);
   1.107 -	if (fbmfns == NULL)
   1.108 -		return -1;
   1.109 +	xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
   1.110 +	map = xc_map_foreign_batch(xenfb->xc, domid,
   1.111 +				   PROT_READ, pgmfns, n_fbdirs);
   1.112 +	if (map == NULL)
   1.113 +		goto out;
   1.114 +	xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
   1.115 +	munmap(map, n_fbdirs * XC_PAGE_SIZE);
   1.116  
   1.117  	xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
   1.118  				PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
   1.119 -	if (xenfb->pub.pixels == NULL) {
   1.120 -		munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
   1.121 -		return -1;
   1.122 -	}
   1.123 +	if (xenfb->pub.pixels == NULL)
   1.124 +		goto out;
   1.125 +
   1.126 +	ret = 0; /* all is fine */
   1.127  
   1.128 -	return munmap(fbmfns, n_fbdirs * XC_PAGE_SIZE);
   1.129 + out:
   1.130 +	if (pgmfns)
   1.131 +		free(pgmfns);
   1.132 +	if (fbmfns)
   1.133 +		free(fbmfns);
   1.134 +	return ret;
   1.135  }
   1.136  
   1.137  static int xenfb_bind(struct xenfb_device *dev)
   1.138 @@ -368,6 +441,9 @@ static int xenfb_bind(struct xenfb_devic
   1.139  	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
   1.140  			    &evtchn) < 0)
   1.141  		return -1;
   1.142 +	if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "protocol", "%63s",
   1.143 +			    xenfb->protocol) < 0)
   1.144 +		xenfb->protocol[0] = '\0';
   1.145  
   1.146  	dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
   1.147  					       dev->otherend_id, evtchn);