debuggers.hg
changeset 13602:d54c8dab1e64
bimodal pvfb backend: Deal with both 32 and 64 bit frontends.
Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
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);