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