1 /* 2 * xen paravirt framebuffer backend 3 * 4 * Copyright IBM, Corp. 2005-2006 5 * Copyright Red Hat, Inc. 2006-2008 6 * 7 * Authors: 8 * Anthony Liguori <aliguori@us.ibm.com>, 9 * Markus Armbruster <armbru@redhat.com>, 10 * Daniel P. Berrange <berrange@redhat.com>, 11 * Pat Campbell <plc@novell.com>, 12 * Gerd Hoffmann <kraxel@redhat.com> 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; under version 2 of the License. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License along 24 * with this program; if not, see <http://www.gnu.org/licenses/>. 25 */ 26 27 #include "qemu/osdep.h" 28 #include <sys/mman.h> 29 30 #include "hw/hw.h" 31 #include "ui/console.h" 32 #include "sysemu/char.h" 33 #include "hw/xen/xen_backend.h" 34 35 #include <xen/event_channel.h> 36 #include <xen/io/fbif.h> 37 #include <xen/io/kbdif.h> 38 #include <xen/io/protocols.h> 39 40 #include "trace.h" 41 42 #ifndef BTN_LEFT 43 #define BTN_LEFT 0x110 /* from <linux/input.h> */ 44 #endif 45 46 /* -------------------------------------------------------------------- */ 47 48 struct common { 49 struct XenDevice xendev; /* must be first */ 50 void *page; 51 QemuConsole *con; 52 }; 53 54 struct XenInput { 55 struct common c; 56 int abs_pointer_wanted; /* Whether guest supports absolute pointer */ 57 int button_state; /* Last seen pointer button state */ 58 int extended; 59 QEMUPutMouseEntry *qmouse; 60 }; 61 62 #define UP_QUEUE 8 63 64 struct XenFB { 65 struct common c; 66 size_t fb_len; 67 int row_stride; 68 int depth; 69 int width; 70 int height; 71 int offset; 72 void *pixels; 73 int fbpages; 74 int feature_update; 75 int bug_trigger; 76 int have_console; 77 int do_resize; 78 79 struct { 80 int x,y,w,h; 81 } up_rects[UP_QUEUE]; 82 int up_count; 83 int up_fullscreen; 84 }; 85 86 /* -------------------------------------------------------------------- */ 87 88 static int common_bind(struct common *c) 89 { 90 uint64_t val; 91 xen_pfn_t mfn; 92 93 if (xenstore_read_fe_uint64(&c->xendev, "page-ref", &val) == -1) 94 return -1; 95 mfn = (xen_pfn_t)val; 96 assert(val == mfn); 97 98 if (xenstore_read_fe_int(&c->xendev, "event-channel", &c->xendev.remote_port) == -1) 99 return -1; 100 101 c->page = xenforeignmemory_map(xen_fmem, c->xendev.dom, 102 PROT_READ | PROT_WRITE, 1, &mfn, NULL); 103 if (c->page == NULL) 104 return -1; 105 106 xen_be_bind_evtchn(&c->xendev); 107 xen_be_printf(&c->xendev, 1, "ring mfn %"PRI_xen_pfn", remote-port %d, local-port %d\n", 108 mfn, c->xendev.remote_port, c->xendev.local_port); 109 110 return 0; 111 } 112 113 static void common_unbind(struct common *c) 114 { 115 xen_be_unbind_evtchn(&c->xendev); 116 if (c->page) { 117 xenforeignmemory_unmap(xen_fmem, c->page, 1); 118 c->page = NULL; 119 } 120 } 121 122 /* -------------------------------------------------------------------- */ 123 124 #if 0 125 /* 126 * These two tables are not needed any more, but left in here 127 * intentionally as documentation, to show how scancode2linux[] 128 * was generated. 129 * 130 * Tables to map from scancode to Linux input layer keycode. 131 * Scancodes are hardware-specific. These maps assumes a 132 * standard AT or PS/2 keyboard which is what QEMU feeds us. 133 */ 134 const unsigned char atkbd_set2_keycode[512] = { 135 136 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117, 137 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0, 138 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, 139 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185, 140 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, 141 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85, 142 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0, 143 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, 144 145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125, 147 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127, 148 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142, 149 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0, 150 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0, 151 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112, 152 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0, 153 154 }; 155 156 const unsigned char atkbd_unxlate_table[128] = { 157 158 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13, 159 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, 160 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, 161 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3, 162 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105, 163 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63, 164 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111, 165 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110 166 167 }; 168 #endif 169 170 /* 171 * for (i = 0; i < 128; i++) { 172 * scancode2linux[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]]; 173 * scancode2linux[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80]; 174 * } 175 */ 176 static const unsigned char scancode2linux[512] = { 177 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 178 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 179 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 180 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 181 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 182 80, 81, 82, 83, 99, 0, 86, 87, 88,117, 0, 0, 95,183,184,185, 183 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184 93, 0, 0, 89, 0, 0, 85, 91, 90, 92, 0, 94, 0,124,121, 0, 185 186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 187 165, 0, 0, 0, 0, 0, 0, 0, 0,163, 0, 0, 96, 97, 0, 0, 188 113,140,164, 0,166, 0, 0, 0, 0, 0,255, 0, 0, 0,114, 0, 189 115, 0,150, 0, 0, 98,255, 99,100, 0, 0, 0, 0, 0, 0, 0, 190 0, 0, 0, 0, 0,119,119,102,103,104, 0,105,112,106,118,107, 191 108,109,110,111, 0, 0, 0, 0, 0, 0, 0,125,126,127,116,142, 192 0, 0, 0,143, 0,217,156,173,128,159,158,157,155,226, 0,112, 193 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 194 }; 195 196 /* Send an event to the keyboard frontend driver */ 197 static int xenfb_kbd_event(struct XenInput *xenfb, 198 union xenkbd_in_event *event) 199 { 200 struct xenkbd_page *page = xenfb->c.page; 201 uint32_t prod; 202 203 if (xenfb->c.xendev.be_state != XenbusStateConnected) 204 return 0; 205 if (!page) 206 return 0; 207 208 prod = page->in_prod; 209 if (prod - page->in_cons == XENKBD_IN_RING_LEN) { 210 errno = EAGAIN; 211 return -1; 212 } 213 214 xen_mb(); /* ensure ring space available */ 215 XENKBD_IN_RING_REF(page, prod) = *event; 216 xen_wmb(); /* ensure ring contents visible */ 217 page->in_prod = prod + 1; 218 return xen_be_send_notify(&xenfb->c.xendev); 219 } 220 221 /* Send a keyboard (or mouse button) event */ 222 static int xenfb_send_key(struct XenInput *xenfb, bool down, int keycode) 223 { 224 union xenkbd_in_event event; 225 226 memset(&event, 0, XENKBD_IN_EVENT_SIZE); 227 event.type = XENKBD_TYPE_KEY; 228 event.key.pressed = down ? 1 : 0; 229 event.key.keycode = keycode; 230 231 return xenfb_kbd_event(xenfb, &event); 232 } 233 234 /* Send a relative mouse movement event */ 235 static int xenfb_send_motion(struct XenInput *xenfb, 236 int rel_x, int rel_y, int rel_z) 237 { 238 union xenkbd_in_event event; 239 240 memset(&event, 0, XENKBD_IN_EVENT_SIZE); 241 event.type = XENKBD_TYPE_MOTION; 242 event.motion.rel_x = rel_x; 243 event.motion.rel_y = rel_y; 244 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030207 245 event.motion.rel_z = rel_z; 246 #endif 247 248 return xenfb_kbd_event(xenfb, &event); 249 } 250 251 /* Send an absolute mouse movement event */ 252 static int xenfb_send_position(struct XenInput *xenfb, 253 int abs_x, int abs_y, int z) 254 { 255 union xenkbd_in_event event; 256 257 memset(&event, 0, XENKBD_IN_EVENT_SIZE); 258 event.type = XENKBD_TYPE_POS; 259 event.pos.abs_x = abs_x; 260 event.pos.abs_y = abs_y; 261 #if __XEN_LATEST_INTERFACE_VERSION__ == 0x00030207 262 event.pos.abs_z = z; 263 #endif 264 #if __XEN_LATEST_INTERFACE_VERSION__ >= 0x00030208 265 event.pos.rel_z = z; 266 #endif 267 268 return xenfb_kbd_event(xenfb, &event); 269 } 270 271 /* 272 * Send a key event from the client to the guest OS 273 * QEMU gives us a raw scancode from an AT / PS/2 style keyboard. 274 * We have to turn this into a Linux Input layer keycode. 275 * 276 * Extra complexity from the fact that with extended scancodes 277 * (like those produced by arrow keys) this method gets called 278 * twice, but we only want to send a single event. So we have to 279 * track the '0xe0' scancode state & collapse the extended keys 280 * as needed. 281 * 282 * Wish we could just send scancodes straight to the guest which 283 * already has code for dealing with this... 284 */ 285 static void xenfb_key_event(void *opaque, int scancode) 286 { 287 struct XenInput *xenfb = opaque; 288 int down = 1; 289 290 if (scancode == 0xe0) { 291 xenfb->extended = 1; 292 return; 293 } else if (scancode & 0x80) { 294 scancode &= 0x7f; 295 down = 0; 296 } 297 if (xenfb->extended) { 298 scancode |= 0x80; 299 xenfb->extended = 0; 300 } 301 xenfb_send_key(xenfb, down, scancode2linux[scancode]); 302 } 303 304 /* 305 * Send a mouse event from the client to the guest OS 306 * 307 * The QEMU mouse can be in either relative, or absolute mode. 308 * Movement is sent separately from button state, which has to 309 * be encoded as virtual key events. We also don't actually get 310 * given any button up/down events, so have to track changes in 311 * the button state. 312 */ 313 static void xenfb_mouse_event(void *opaque, 314 int dx, int dy, int dz, int button_state) 315 { 316 struct XenInput *xenfb = opaque; 317 DisplaySurface *surface = qemu_console_surface(xenfb->c.con); 318 int dw = surface_width(surface); 319 int dh = surface_height(surface); 320 int i; 321 322 trace_xenfb_mouse_event(opaque, dx, dy, dz, button_state, 323 xenfb->abs_pointer_wanted); 324 if (xenfb->abs_pointer_wanted) 325 xenfb_send_position(xenfb, 326 dx * (dw - 1) / 0x7fff, 327 dy * (dh - 1) / 0x7fff, 328 dz); 329 else 330 xenfb_send_motion(xenfb, dx, dy, dz); 331 332 for (i = 0 ; i < 8 ; i++) { 333 int lastDown = xenfb->button_state & (1 << i); 334 int down = button_state & (1 << i); 335 if (down == lastDown) 336 continue; 337 338 if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) 339 return; 340 } 341 xenfb->button_state = button_state; 342 } 343 344 static int input_init(struct XenDevice *xendev) 345 { 346 xenstore_write_be_int(xendev, "feature-abs-pointer", 1); 347 return 0; 348 } 349 350 static int input_initialise(struct XenDevice *xendev) 351 { 352 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); 353 int rc; 354 355 if (!in->c.con) { 356 xen_be_printf(xendev, 1, "ds not set (yet)\n"); 357 return -1; 358 } 359 360 rc = common_bind(&in->c); 361 if (rc != 0) 362 return rc; 363 364 qemu_add_kbd_event_handler(xenfb_key_event, in); 365 return 0; 366 } 367 368 static void input_connected(struct XenDevice *xendev) 369 { 370 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); 371 372 if (xenstore_read_fe_int(xendev, "request-abs-pointer", 373 &in->abs_pointer_wanted) == -1) { 374 in->abs_pointer_wanted = 0; 375 } 376 377 if (in->qmouse) { 378 qemu_remove_mouse_event_handler(in->qmouse); 379 } 380 trace_xenfb_input_connected(xendev, in->abs_pointer_wanted); 381 in->qmouse = qemu_add_mouse_event_handler(xenfb_mouse_event, in, 382 in->abs_pointer_wanted, 383 "Xen PVFB Mouse"); 384 } 385 386 static void input_disconnect(struct XenDevice *xendev) 387 { 388 struct XenInput *in = container_of(xendev, struct XenInput, c.xendev); 389 390 if (in->qmouse) { 391 qemu_remove_mouse_event_handler(in->qmouse); 392 in->qmouse = NULL; 393 } 394 qemu_add_kbd_event_handler(NULL, NULL); 395 common_unbind(&in->c); 396 } 397 398 static void input_event(struct XenDevice *xendev) 399 { 400 struct XenInput *xenfb = container_of(xendev, struct XenInput, c.xendev); 401 struct xenkbd_page *page = xenfb->c.page; 402 403 /* We don't understand any keyboard events, so just ignore them. */ 404 if (page->out_prod == page->out_cons) 405 return; 406 page->out_cons = page->out_prod; 407 xen_be_send_notify(&xenfb->c.xendev); 408 } 409 410 /* -------------------------------------------------------------------- */ 411 412 static void xenfb_copy_mfns(int mode, int count, xen_pfn_t *dst, void *src) 413 { 414 uint32_t *src32 = src; 415 uint64_t *src64 = src; 416 int i; 417 418 for (i = 0; i < count; i++) 419 dst[i] = (mode == 32) ? src32[i] : src64[i]; 420 } 421 422 static int xenfb_map_fb(struct XenFB *xenfb) 423 { 424 struct xenfb_page *page = xenfb->c.page; 425 char *protocol = xenfb->c.xendev.protocol; 426 int n_fbdirs; 427 xen_pfn_t *pgmfns = NULL; 428 xen_pfn_t *fbmfns = NULL; 429 void *map, *pd; 430 int mode, ret = -1; 431 432 /* default to native */ 433 pd = page->pd; 434 mode = sizeof(unsigned long) * 8; 435 436 if (!protocol) { 437 /* 438 * Undefined protocol, some guesswork needed. 439 * 440 * Old frontends which don't set the protocol use 441 * one page directory only, thus pd[1] must be zero. 442 * pd[1] of the 32bit struct layout and the lower 443 * 32 bits of pd[0] of the 64bit struct layout have 444 * the same location, so we can check that ... 445 */ 446 uint32_t *ptr32 = NULL; 447 uint32_t *ptr64 = NULL; 448 #if defined(__i386__) 449 ptr32 = (void*)page->pd; 450 ptr64 = ((void*)page->pd) + 4; 451 #elif defined(__x86_64__) 452 ptr32 = ((void*)page->pd) - 4; 453 ptr64 = (void*)page->pd; 454 #endif 455 if (ptr32) { 456 if (ptr32[1] == 0) { 457 mode = 32; 458 pd = ptr32; 459 } else { 460 mode = 64; 461 pd = ptr64; 462 } 463 } 464 #if defined(__x86_64__) 465 } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { 466 /* 64bit dom0, 32bit domU */ 467 mode = 32; 468 pd = ((void*)page->pd) - 4; 469 #elif defined(__i386__) 470 } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 0) { 471 /* 32bit dom0, 64bit domU */ 472 mode = 64; 473 pd = ((void*)page->pd) + 4; 474 #endif 475 } 476 477 if (xenfb->pixels) { 478 munmap(xenfb->pixels, xenfb->fbpages * XC_PAGE_SIZE); 479 xenfb->pixels = NULL; 480 } 481 482 xenfb->fbpages = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; 483 n_fbdirs = xenfb->fbpages * mode / 8; 484 n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE; 485 486 pgmfns = g_malloc0(sizeof(xen_pfn_t) * n_fbdirs); 487 fbmfns = g_malloc0(sizeof(xen_pfn_t) * xenfb->fbpages); 488 489 xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd); 490 map = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom, 491 PROT_READ, n_fbdirs, pgmfns, NULL); 492 if (map == NULL) 493 goto out; 494 xenfb_copy_mfns(mode, xenfb->fbpages, fbmfns, map); 495 xenforeignmemory_unmap(xen_fmem, map, n_fbdirs); 496 497 xenfb->pixels = xenforeignmemory_map(xen_fmem, xenfb->c.xendev.dom, 498 PROT_READ, xenfb->fbpages, fbmfns, NULL); 499 if (xenfb->pixels == NULL) 500 goto out; 501 502 ret = 0; /* all is fine */ 503 504 out: 505 g_free(pgmfns); 506 g_free(fbmfns); 507 return ret; 508 } 509 510 static int xenfb_configure_fb(struct XenFB *xenfb, size_t fb_len_lim, 511 int width, int height, int depth, 512 size_t fb_len, int offset, int row_stride) 513 { 514 size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd); 515 size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz; 516 size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz; 517 size_t fb_len_max = fb_pages * XC_PAGE_SIZE; 518 int max_width, max_height; 519 520 if (fb_len_lim > fb_len_max) { 521 xen_be_printf(&xenfb->c.xendev, 0, "fb size limit %zu exceeds %zu, corrected\n", 522 fb_len_lim, fb_len_max); 523 fb_len_lim = fb_len_max; 524 } 525 if (fb_len_lim && fb_len > fb_len_lim) { 526 xen_be_printf(&xenfb->c.xendev, 0, "frontend fb size %zu limited to %zu\n", 527 fb_len, fb_len_lim); 528 fb_len = fb_len_lim; 529 } 530 if (depth != 8 && depth != 16 && depth != 24 && depth != 32) { 531 xen_be_printf(&xenfb->c.xendev, 0, "can't handle frontend fb depth %d\n", 532 depth); 533 return -1; 534 } 535 if (row_stride <= 0 || row_stride > fb_len) { 536 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend stride %d\n", row_stride); 537 return -1; 538 } 539 max_width = row_stride / (depth / 8); 540 if (width < 0 || width > max_width) { 541 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend width %d limited to %d\n", 542 width, max_width); 543 width = max_width; 544 } 545 if (offset < 0 || offset >= fb_len) { 546 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend offset %d (max %zu)\n", 547 offset, fb_len - 1); 548 return -1; 549 } 550 max_height = (fb_len - offset) / row_stride; 551 if (height < 0 || height > max_height) { 552 xen_be_printf(&xenfb->c.xendev, 0, "invalid frontend height %d limited to %d\n", 553 height, max_height); 554 height = max_height; 555 } 556 xenfb->fb_len = fb_len; 557 xenfb->row_stride = row_stride; 558 xenfb->depth = depth; 559 xenfb->width = width; 560 xenfb->height = height; 561 xenfb->offset = offset; 562 xenfb->up_fullscreen = 1; 563 xenfb->do_resize = 1; 564 xen_be_printf(&xenfb->c.xendev, 1, "framebuffer %dx%dx%d offset %d stride %d\n", 565 width, height, depth, offset, row_stride); 566 return 0; 567 } 568 569 /* A convenient function for munging pixels between different depths */ 570 #define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB) \ 571 for (line = y ; line < (y+h) ; line++) { \ 572 SRC_T *src = (SRC_T *)(xenfb->pixels \ 573 + xenfb->offset \ 574 + (line * xenfb->row_stride) \ 575 + (x * xenfb->depth / 8)); \ 576 DST_T *dst = (DST_T *)(data \ 577 + (line * linesize) \ 578 + (x * bpp / 8)); \ 579 int col; \ 580 const int RSS = 32 - (RSB + GSB + BSB); \ 581 const int GSS = 32 - (GSB + BSB); \ 582 const int BSS = 32 - (BSB); \ 583 const uint32_t RSM = (~0U) << (32 - RSB); \ 584 const uint32_t GSM = (~0U) << (32 - GSB); \ 585 const uint32_t BSM = (~0U) << (32 - BSB); \ 586 const int RDS = 32 - (RDB + GDB + BDB); \ 587 const int GDS = 32 - (GDB + BDB); \ 588 const int BDS = 32 - (BDB); \ 589 const uint32_t RDM = (~0U) << (32 - RDB); \ 590 const uint32_t GDM = (~0U) << (32 - GDB); \ 591 const uint32_t BDM = (~0U) << (32 - BDB); \ 592 for (col = x ; col < (x+w) ; col++) { \ 593 uint32_t spix = *src; \ 594 *dst = (((spix << RSS) & RSM & RDM) >> RDS) | \ 595 (((spix << GSS) & GSM & GDM) >> GDS) | \ 596 (((spix << BSS) & BSM & BDM) >> BDS); \ 597 src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8); \ 598 dst = (DST_T *) ((unsigned long) dst + bpp / 8); \ 599 } \ 600 } 601 602 603 /* 604 * This copies data from the guest framebuffer region, into QEMU's 605 * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer 606 * uses something else we must convert and copy, otherwise we can 607 * supply the buffer directly and no thing here. 608 */ 609 static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) 610 { 611 DisplaySurface *surface = qemu_console_surface(xenfb->c.con); 612 int line, oops = 0; 613 int bpp = surface_bits_per_pixel(surface); 614 int linesize = surface_stride(surface); 615 uint8_t *data = surface_data(surface); 616 617 if (!is_buffer_shared(surface)) { 618 switch (xenfb->depth) { 619 case 8: 620 if (bpp == 16) { 621 BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5); 622 } else if (bpp == 32) { 623 BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8); 624 } else { 625 oops = 1; 626 } 627 break; 628 case 24: 629 if (bpp == 16) { 630 BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5); 631 } else if (bpp == 32) { 632 BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8); 633 } else { 634 oops = 1; 635 } 636 break; 637 default: 638 oops = 1; 639 } 640 } 641 if (oops) /* should not happen */ 642 xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n", 643 __FUNCTION__, xenfb->depth, bpp); 644 645 dpy_gfx_update(xenfb->c.con, x, y, w, h); 646 } 647 648 #ifdef XENFB_TYPE_REFRESH_PERIOD 649 static int xenfb_queue_full(struct XenFB *xenfb) 650 { 651 struct xenfb_page *page = xenfb->c.page; 652 uint32_t cons, prod; 653 654 if (!page) 655 return 1; 656 657 prod = page->in_prod; 658 cons = page->in_cons; 659 return prod - cons == XENFB_IN_RING_LEN; 660 } 661 662 static void xenfb_send_event(struct XenFB *xenfb, union xenfb_in_event *event) 663 { 664 uint32_t prod; 665 struct xenfb_page *page = xenfb->c.page; 666 667 prod = page->in_prod; 668 /* caller ensures !xenfb_queue_full() */ 669 xen_mb(); /* ensure ring space available */ 670 XENFB_IN_RING_REF(page, prod) = *event; 671 xen_wmb(); /* ensure ring contents visible */ 672 page->in_prod = prod + 1; 673 674 xen_be_send_notify(&xenfb->c.xendev); 675 } 676 677 static void xenfb_send_refresh_period(struct XenFB *xenfb, int period) 678 { 679 union xenfb_in_event event; 680 681 memset(&event, 0, sizeof(event)); 682 event.type = XENFB_TYPE_REFRESH_PERIOD; 683 event.refresh_period.period = period; 684 xenfb_send_event(xenfb, &event); 685 } 686 #endif 687 688 /* 689 * Periodic update of display. 690 * Also transmit the refresh interval to the frontend. 691 * 692 * Never ever do any qemu display operations 693 * (resize, screen update) outside this function. 694 * Our screen might be inactive. When asked for 695 * an update we know it is active. 696 */ 697 static void xenfb_update(void *opaque) 698 { 699 struct XenFB *xenfb = opaque; 700 DisplaySurface *surface; 701 int i; 702 703 if (xenfb->c.xendev.be_state != XenbusStateConnected) 704 return; 705 706 if (!xenfb->feature_update) { 707 /* we don't get update notifications, thus use the 708 * sledge hammer approach ... */ 709 xenfb->up_fullscreen = 1; 710 } 711 712 /* resize if needed */ 713 if (xenfb->do_resize) { 714 pixman_format_code_t format; 715 716 xenfb->do_resize = 0; 717 switch (xenfb->depth) { 718 case 16: 719 case 32: 720 /* console.c supported depth -> buffer can be used directly */ 721 format = qemu_default_pixman_format(xenfb->depth, true); 722 surface = qemu_create_displaysurface_from 723 (xenfb->width, xenfb->height, format, 724 xenfb->row_stride, xenfb->pixels + xenfb->offset); 725 break; 726 default: 727 /* we must convert stuff */ 728 surface = qemu_create_displaysurface(xenfb->width, xenfb->height); 729 break; 730 } 731 dpy_gfx_replace_surface(xenfb->c.con, surface); 732 xen_be_printf(&xenfb->c.xendev, 1, "update: resizing: %dx%d @ %d bpp%s\n", 733 xenfb->width, xenfb->height, xenfb->depth, 734 is_buffer_shared(surface) ? " (shared)" : ""); 735 xenfb->up_fullscreen = 1; 736 } 737 738 /* run queued updates */ 739 if (xenfb->up_fullscreen) { 740 xen_be_printf(&xenfb->c.xendev, 3, "update: fullscreen\n"); 741 xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); 742 } else if (xenfb->up_count) { 743 xen_be_printf(&xenfb->c.xendev, 3, "update: %d rects\n", xenfb->up_count); 744 for (i = 0; i < xenfb->up_count; i++) 745 xenfb_guest_copy(xenfb, 746 xenfb->up_rects[i].x, 747 xenfb->up_rects[i].y, 748 xenfb->up_rects[i].w, 749 xenfb->up_rects[i].h); 750 } else { 751 xen_be_printf(&xenfb->c.xendev, 3, "update: nothing\n"); 752 } 753 xenfb->up_count = 0; 754 xenfb->up_fullscreen = 0; 755 } 756 757 static void xenfb_update_interval(void *opaque, uint64_t interval) 758 { 759 struct XenFB *xenfb = opaque; 760 761 if (xenfb->feature_update) { 762 #ifdef XENFB_TYPE_REFRESH_PERIOD 763 if (xenfb_queue_full(xenfb)) { 764 return; 765 } 766 xenfb_send_refresh_period(xenfb, interval); 767 #endif 768 } 769 } 770 771 /* QEMU display state changed, so refresh the framebuffer copy */ 772 static void xenfb_invalidate(void *opaque) 773 { 774 struct XenFB *xenfb = opaque; 775 xenfb->up_fullscreen = 1; 776 } 777 778 static void xenfb_handle_events(struct XenFB *xenfb) 779 { 780 uint32_t prod, cons, out_cons; 781 struct xenfb_page *page = xenfb->c.page; 782 783 prod = page->out_prod; 784 out_cons = page->out_cons; 785 if (prod - out_cons >= XENFB_OUT_RING_LEN) { 786 return; 787 } 788 xen_rmb(); /* ensure we see ring contents up to prod */ 789 for (cons = out_cons; cons != prod; cons++) { 790 union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); 791 uint8_t type = event->type; 792 int x, y, w, h; 793 794 switch (type) { 795 case XENFB_TYPE_UPDATE: 796 if (xenfb->up_count == UP_QUEUE) 797 xenfb->up_fullscreen = 1; 798 if (xenfb->up_fullscreen) 799 break; 800 x = MAX(event->update.x, 0); 801 y = MAX(event->update.y, 0); 802 w = MIN(event->update.width, xenfb->width - x); 803 h = MIN(event->update.height, xenfb->height - y); 804 if (w < 0 || h < 0) { 805 xen_be_printf(&xenfb->c.xendev, 1, "bogus update ignored\n"); 806 break; 807 } 808 if (x != event->update.x || 809 y != event->update.y || 810 w != event->update.width || 811 h != event->update.height) { 812 xen_be_printf(&xenfb->c.xendev, 1, "bogus update clipped\n"); 813 } 814 if (w == xenfb->width && h > xenfb->height / 2) { 815 /* scroll detector: updated more than 50% of the lines, 816 * don't bother keeping track of the rectangles then */ 817 xenfb->up_fullscreen = 1; 818 } else { 819 xenfb->up_rects[xenfb->up_count].x = x; 820 xenfb->up_rects[xenfb->up_count].y = y; 821 xenfb->up_rects[xenfb->up_count].w = w; 822 xenfb->up_rects[xenfb->up_count].h = h; 823 xenfb->up_count++; 824 } 825 break; 826 #ifdef XENFB_TYPE_RESIZE 827 case XENFB_TYPE_RESIZE: 828 if (xenfb_configure_fb(xenfb, xenfb->fb_len, 829 event->resize.width, 830 event->resize.height, 831 event->resize.depth, 832 xenfb->fb_len, 833 event->resize.offset, 834 event->resize.stride) < 0) 835 break; 836 xenfb_invalidate(xenfb); 837 break; 838 #endif 839 } 840 } 841 xen_mb(); /* ensure we're done with ring contents */ 842 page->out_cons = cons; 843 } 844 845 static int fb_init(struct XenDevice *xendev) 846 { 847 #ifdef XENFB_TYPE_RESIZE 848 xenstore_write_be_int(xendev, "feature-resize", 1); 849 #endif 850 return 0; 851 } 852 853 static int fb_initialise(struct XenDevice *xendev) 854 { 855 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); 856 struct xenfb_page *fb_page; 857 int videoram; 858 int rc; 859 860 if (xenstore_read_fe_int(xendev, "videoram", &videoram) == -1) 861 videoram = 0; 862 863 rc = common_bind(&fb->c); 864 if (rc != 0) 865 return rc; 866 867 fb_page = fb->c.page; 868 rc = xenfb_configure_fb(fb, videoram * 1024 * 1024U, 869 fb_page->width, fb_page->height, fb_page->depth, 870 fb_page->mem_length, 0, fb_page->line_length); 871 if (rc != 0) 872 return rc; 873 874 rc = xenfb_map_fb(fb); 875 if (rc != 0) 876 return rc; 877 878 #if 0 /* handled in xen_init_display() for now */ 879 if (!fb->have_console) { 880 fb->c.ds = graphic_console_init(xenfb_update, 881 xenfb_invalidate, 882 NULL, 883 NULL, 884 fb); 885 fb->have_console = 1; 886 } 887 #endif 888 889 if (xenstore_read_fe_int(xendev, "feature-update", &fb->feature_update) == -1) 890 fb->feature_update = 0; 891 if (fb->feature_update) 892 xenstore_write_be_int(xendev, "request-update", 1); 893 894 xen_be_printf(xendev, 1, "feature-update=%d, videoram=%d\n", 895 fb->feature_update, videoram); 896 return 0; 897 } 898 899 static void fb_disconnect(struct XenDevice *xendev) 900 { 901 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); 902 903 /* 904 * FIXME: qemu can't un-init gfx display (yet?). 905 * Replacing the framebuffer with anonymous shared memory 906 * instead. This releases the guest pages and keeps qemu happy. 907 */ 908 xenforeignmemory_unmap(xen_fmem, fb->pixels, fb->fbpages); 909 fb->pixels = mmap(fb->pixels, fb->fbpages * XC_PAGE_SIZE, 910 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 911 -1, 0); 912 if (fb->pixels == MAP_FAILED) { 913 xen_be_printf(xendev, 0, 914 "Couldn't replace the framebuffer with anonymous memory errno=%d\n", 915 errno); 916 } 917 common_unbind(&fb->c); 918 fb->feature_update = 0; 919 fb->bug_trigger = 0; 920 } 921 922 static void fb_frontend_changed(struct XenDevice *xendev, const char *node) 923 { 924 struct XenFB *fb = container_of(xendev, struct XenFB, c.xendev); 925 926 /* 927 * Set state to Connected *again* once the frontend switched 928 * to connected. We must trigger the watch a second time to 929 * workaround a frontend bug. 930 */ 931 if (fb->bug_trigger == 0 && strcmp(node, "state") == 0 && 932 xendev->fe_state == XenbusStateConnected && 933 xendev->be_state == XenbusStateConnected) { 934 xen_be_printf(xendev, 2, "re-trigger connected (frontend bug)\n"); 935 xen_be_set_state(xendev, XenbusStateConnected); 936 fb->bug_trigger = 1; /* only once */ 937 } 938 } 939 940 static void fb_event(struct XenDevice *xendev) 941 { 942 struct XenFB *xenfb = container_of(xendev, struct XenFB, c.xendev); 943 944 xenfb_handle_events(xenfb); 945 xen_be_send_notify(&xenfb->c.xendev); 946 } 947 948 /* -------------------------------------------------------------------- */ 949 950 struct XenDevOps xen_kbdmouse_ops = { 951 .size = sizeof(struct XenInput), 952 .init = input_init, 953 .initialise = input_initialise, 954 .connected = input_connected, 955 .disconnect = input_disconnect, 956 .event = input_event, 957 }; 958 959 struct XenDevOps xen_framebuffer_ops = { 960 .size = sizeof(struct XenFB), 961 .init = fb_init, 962 .initialise = fb_initialise, 963 .disconnect = fb_disconnect, 964 .event = fb_event, 965 .frontend_changed = fb_frontend_changed, 966 }; 967 968 static const GraphicHwOps xenfb_ops = { 969 .invalidate = xenfb_invalidate, 970 .gfx_update = xenfb_update, 971 .update_interval = xenfb_update_interval, 972 }; 973 974 /* 975 * FIXME/TODO: Kill this. 976 * Temporary needed while DisplayState reorganization is in flight. 977 */ 978 void xen_init_display(int domid) 979 { 980 struct XenDevice *xfb, *xin; 981 struct XenFB *fb; 982 struct XenInput *in; 983 int i = 0; 984 985 wait_more: 986 i++; 987 main_loop_wait(true); 988 xfb = xen_be_find_xendev("vfb", domid, 0); 989 xin = xen_be_find_xendev("vkbd", domid, 0); 990 if (!xfb || !xin) { 991 if (i < 256) { 992 usleep(10000); 993 goto wait_more; 994 } 995 xen_be_printf(NULL, 1, "displaystate setup failed\n"); 996 return; 997 } 998 999 /* vfb */ 1000 fb = container_of(xfb, struct XenFB, c.xendev); 1001 fb->c.con = graphic_console_init(NULL, 0, &xenfb_ops, fb); 1002 fb->have_console = 1; 1003 1004 /* vkbd */ 1005 in = container_of(xin, struct XenInput, c.xendev); 1006 in->c.con = fb->c.con; 1007 1008 /* retry ->init() */ 1009 xen_be_check_state(xin); 1010 xen_be_check_state(xfb); 1011 } 1012