1 /* Copyright (C) 2011 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 #include "android/utils/panic.h" 13 #include "android/utils/system.h" 14 #include "hw/goldfish_pipe.h" 15 #include "hw/goldfish_device.h" 16 #include "qemu-timer.h" 17 #ifdef CONFIG_KVM 18 #include "kvm.h" 19 #endif 20 21 #define DEBUG 0 22 23 /* Set to 1 to debug i/o register reads/writes */ 24 #define DEBUG_REGS 0 25 26 #if DEBUG >= 1 27 # define D(...) fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n") 28 #else 29 # define D(...) (void)0 30 #endif 31 32 #if DEBUG >= 2 33 # define DD(...) fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n") 34 #else 35 # define DD(...) (void)0 36 #endif 37 38 #if DEBUG_REGS >= 1 39 # define DR(...) D(__VA_ARGS__) 40 #else 41 # define DR(...) (void)0 42 #endif 43 44 #define E(...) fprintf(stderr, "ERROR:" __VA_ARGS__), fprintf(stderr, "\n") 45 46 /* Set to 1 to enable the 'zero' pipe type, useful for debugging */ 47 #define DEBUG_ZERO_PIPE 1 48 49 /* Set to 1 to enable the 'pingpong' pipe type, useful for debugging */ 50 #define DEBUG_PINGPONG_PIPE 1 51 52 /* Set to 1 to enable the 'throttle' pipe type, useful for debugging */ 53 #define DEBUG_THROTTLE_PIPE 1 54 55 /*********************************************************************** 56 *********************************************************************** 57 ***** 58 ***** P I P E S E R V I C E R E G I S T R A T I O N 59 ***** 60 *****/ 61 62 #define MAX_PIPE_SERVICES 8 63 typedef struct { 64 const char* name; 65 void* opaque; 66 GoldfishPipeFuncs funcs; 67 } PipeService; 68 69 typedef struct { 70 int count; 71 PipeService services[MAX_PIPE_SERVICES]; 72 } PipeServices; 73 74 static PipeServices _pipeServices[1]; 75 76 void 77 goldfish_pipe_add_type(const char* pipeName, 78 void* pipeOpaque, 79 const GoldfishPipeFuncs* pipeFuncs ) 80 { 81 PipeServices* list = _pipeServices; 82 int count = list->count; 83 84 if (count >= MAX_PIPE_SERVICES) { 85 APANIC("Too many goldfish pipe services (%d)", count); 86 } 87 88 list->services[count].name = pipeName; 89 list->services[count].opaque = pipeOpaque; 90 list->services[count].funcs = pipeFuncs[0]; 91 92 list->count++; 93 } 94 95 static const PipeService* 96 goldfish_pipe_find_type(const char* pipeName) 97 { 98 PipeServices* list = _pipeServices; 99 int count = list->count; 100 int nn; 101 102 for (nn = 0; nn < count; nn++) { 103 if (!strcmp(list->services[nn].name, pipeName)) { 104 return &list->services[nn]; 105 } 106 } 107 return NULL; 108 } 109 110 111 /*********************************************************************** 112 *********************************************************************** 113 ***** 114 ***** P I P E C O N N E C T I O N S 115 ***** 116 *****/ 117 118 typedef struct PipeDevice PipeDevice; 119 120 typedef struct Pipe { 121 struct Pipe* next; 122 struct Pipe* next_waked; 123 PipeDevice* device; 124 uint32_t channel; 125 void* opaque; 126 const GoldfishPipeFuncs* funcs; 127 unsigned char wanted; 128 char closed; 129 } Pipe; 130 131 /* Forward */ 132 static void* pipeConnector_new(Pipe* pipe); 133 134 Pipe* 135 pipe_new(uint32_t channel, PipeDevice* dev) 136 { 137 Pipe* pipe; 138 ANEW0(pipe); 139 pipe->channel = channel; 140 pipe->device = dev; 141 pipe->opaque = pipeConnector_new(pipe); 142 return pipe; 143 } 144 145 static Pipe** 146 pipe_list_findp_channel( Pipe** list, uint32_t channel ) 147 { 148 Pipe** pnode = list; 149 for (;;) { 150 Pipe* node = *pnode; 151 if (node == NULL || node->channel == channel) { 152 break; 153 } 154 pnode = &node->next; 155 } 156 return pnode; 157 } 158 159 #if 0 160 static Pipe** 161 pipe_list_findp_opaque( Pipe** list, void* opaque ) 162 { 163 Pipe** pnode = list; 164 for (;;) { 165 Pipe* node = *pnode; 166 if (node == NULL || node->opaque == opaque) { 167 break; 168 } 169 pnode = &node->next; 170 } 171 return pnode; 172 } 173 #endif 174 175 static Pipe** 176 pipe_list_findp_waked( Pipe** list, Pipe* pipe ) 177 { 178 Pipe** pnode = list; 179 for (;;) { 180 Pipe* node = *pnode; 181 if (node == NULL || node == pipe) { 182 break; 183 } 184 pnode = &node->next_waked; 185 } 186 return pnode; 187 } 188 189 190 static void 191 pipe_list_remove_waked( Pipe** list, Pipe* pipe ) 192 { 193 Pipe** lookup = pipe_list_findp_waked(list, pipe); 194 Pipe* node = *lookup; 195 196 if (node != NULL) { 197 (*lookup) = node->next_waked; 198 node->next_waked = NULL; 199 } 200 } 201 202 /*********************************************************************** 203 *********************************************************************** 204 ***** 205 ***** P I P E C O N N E C T O R S 206 ***** 207 *****/ 208 209 /* These are used to handle the initial connection attempt, where the 210 * client is going to write the name of the pipe service it wants to 211 * connect to, followed by a terminating zero. 212 */ 213 typedef struct { 214 Pipe* pipe; 215 char buffer[128]; 216 int buffpos; 217 } PipeConnector; 218 219 static const GoldfishPipeFuncs pipeConnector_funcs; // forward 220 221 void* 222 pipeConnector_new(Pipe* pipe) 223 { 224 PipeConnector* pcon; 225 226 ANEW0(pcon); 227 pcon->pipe = pipe; 228 pipe->funcs = &pipeConnector_funcs; 229 return pcon; 230 } 231 232 static void 233 pipeConnector_close( void* opaque ) 234 { 235 PipeConnector* pcon = opaque; 236 AFREE(pcon); 237 } 238 239 static int 240 pipeConnector_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers ) 241 { 242 PipeConnector* pcon = opaque; 243 const GoldfishPipeBuffer* buffers_limit = buffers + numBuffers; 244 int ret = 0; 245 246 DD("%s: channel=0x%x numBuffers=%d", __FUNCTION__, 247 pcon->pipe->channel, 248 numBuffers); 249 250 while (buffers < buffers_limit) { 251 int avail; 252 253 DD("%s: buffer data (%3d bytes): '%.*s'", __FUNCTION__, 254 buffers[0].size, buffers[0].size, buffers[0].data); 255 256 if (buffers[0].size == 0) { 257 buffers++; 258 continue; 259 } 260 261 avail = sizeof(pcon->buffer) - pcon->buffpos; 262 if (avail > buffers[0].size) 263 avail = buffers[0].size; 264 265 if (avail > 0) { 266 memcpy(pcon->buffer + pcon->buffpos, buffers[0].data, avail); 267 pcon->buffpos += avail; 268 ret += avail; 269 } 270 buffers++; 271 } 272 273 /* Now check that our buffer contains a zero-terminated string */ 274 if (memchr(pcon->buffer, '\0', pcon->buffpos) != NULL) { 275 /* Acceptable formats for the connection string are: 276 * 277 * pipe:<name> 278 * pipe:<name>:<arguments> 279 */ 280 char* pipeName; 281 char* pipeArgs; 282 283 D("%s: connector: '%s'", __FUNCTION__, pcon->buffer); 284 285 if (memcmp(pcon->buffer, "pipe:", 5) != 0) { 286 /* Nope, we don't handle these for now. */ 287 D("%s: Unknown pipe connection: '%s'", __FUNCTION__, pcon->buffer); 288 return PIPE_ERROR_INVAL; 289 } 290 291 pipeName = pcon->buffer + 5; 292 pipeArgs = strchr(pipeName, ':'); 293 294 if (pipeArgs != NULL) { 295 *pipeArgs++ = '\0'; 296 } 297 298 Pipe* pipe = pcon->pipe; 299 const PipeService* svc = goldfish_pipe_find_type(pipeName); 300 if (svc == NULL) { 301 D("%s: Unknown server!", __FUNCTION__); 302 return PIPE_ERROR_INVAL; 303 } 304 305 void* peer = svc->funcs.init(pipe, svc->opaque, pipeArgs); 306 if (peer == NULL) { 307 D("%s: Initialization failed!", __FUNCTION__); 308 return PIPE_ERROR_INVAL; 309 } 310 311 /* Do the evil switch now */ 312 pipe->opaque = peer; 313 pipe->funcs = &svc->funcs; 314 AFREE(pcon); 315 } 316 317 return ret; 318 } 319 320 static int 321 pipeConnector_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers ) 322 { 323 return PIPE_ERROR_IO; 324 } 325 326 static unsigned 327 pipeConnector_poll( void* opaque ) 328 { 329 return PIPE_POLL_OUT; 330 } 331 332 static void 333 pipeConnector_wakeOn( void* opaque, int flags ) 334 { 335 /* nothing, really should never happen */ 336 } 337 338 static const GoldfishPipeFuncs pipeConnector_funcs = { 339 NULL, /* init */ 340 pipeConnector_close, /* should rarely happen */ 341 pipeConnector_sendBuffers, /* the interesting stuff */ 342 pipeConnector_recvBuffers, /* should not happen */ 343 pipeConnector_poll, /* should not happen */ 344 pipeConnector_wakeOn, /* should not happen */ 345 }; 346 347 /*********************************************************************** 348 *********************************************************************** 349 ***** 350 ***** Z E R O P I P E S 351 ***** 352 *****/ 353 354 /* A simple pipe service that mimics /dev/zero, you can write anything to 355 * it, and you can always read any number of zeros from it. Useful for debugging 356 * the kernel driver. 357 */ 358 #if DEBUG_ZERO_PIPE 359 360 typedef struct { 361 void* hwpipe; 362 } ZeroPipe; 363 364 static void* 365 zeroPipe_init( void* hwpipe, void* svcOpaque, const char* args ) 366 { 367 ZeroPipe* zpipe; 368 369 D("%s: hwpipe=%p", __FUNCTION__, hwpipe); 370 ANEW0(zpipe); 371 zpipe->hwpipe = hwpipe; 372 return zpipe; 373 } 374 375 static void 376 zeroPipe_close( void* opaque ) 377 { 378 ZeroPipe* zpipe = opaque; 379 380 D("%s: hwpipe=%p", __FUNCTION__, zpipe->hwpipe); 381 AFREE(zpipe); 382 } 383 384 static int 385 zeroPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers ) 386 { 387 int ret = 0; 388 while (numBuffers > 0) { 389 ret += buffers[0].size; 390 buffers++; 391 numBuffers--; 392 } 393 return ret; 394 } 395 396 static int 397 zeroPipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers ) 398 { 399 int ret = 0; 400 while (numBuffers > 0) { 401 ret += buffers[0].size; 402 memset(buffers[0].data, 0, buffers[0].size); 403 buffers++; 404 numBuffers--; 405 } 406 return ret; 407 } 408 409 static unsigned 410 zeroPipe_poll( void* opaque ) 411 { 412 return PIPE_POLL_IN | PIPE_POLL_OUT; 413 } 414 415 static void 416 zeroPipe_wakeOn( void* opaque, int flags ) 417 { 418 /* nothing to do here */ 419 } 420 421 static const GoldfishPipeFuncs zeroPipe_funcs = { 422 zeroPipe_init, 423 zeroPipe_close, 424 zeroPipe_sendBuffers, 425 zeroPipe_recvBuffers, 426 zeroPipe_poll, 427 zeroPipe_wakeOn, 428 }; 429 430 #endif /* DEBUG_ZERO */ 431 432 /*********************************************************************** 433 *********************************************************************** 434 ***** 435 ***** P I N G P O N G P I P E S 436 ***** 437 *****/ 438 439 /* Similar debug service that sends back anything it receives */ 440 /* All data is kept in a circular dynamic buffer */ 441 442 #if DEBUG_PINGPONG_PIPE 443 444 /* Initial buffer size */ 445 #define PINGPONG_SIZE 1024 446 447 typedef struct { 448 void* hwpipe; 449 uint8_t* buffer; 450 size_t size; 451 size_t pos; 452 size_t count; 453 unsigned flags; 454 } PingPongPipe; 455 456 static void 457 pingPongPipe_init0( PingPongPipe* pipe, void* hwpipe, void* svcOpaque ) 458 { 459 pipe->hwpipe = hwpipe; 460 pipe->size = PINGPONG_SIZE; 461 pipe->buffer = malloc(pipe->size); 462 pipe->pos = 0; 463 pipe->count = 0; 464 } 465 466 static void* 467 pingPongPipe_init( void* hwpipe, void* svcOpaque, const char* args ) 468 { 469 PingPongPipe* ppipe; 470 471 D("%s: hwpipe=%p", __FUNCTION__, hwpipe); 472 ANEW0(ppipe); 473 pingPongPipe_init0(ppipe, hwpipe, svcOpaque); 474 return ppipe; 475 } 476 477 static void 478 pingPongPipe_close( void* opaque ) 479 { 480 PingPongPipe* ppipe = opaque; 481 482 D("%s: hwpipe=%p (pos=%d count=%d size=%d)", __FUNCTION__, 483 ppipe->hwpipe, ppipe->pos, ppipe->count, ppipe->size); 484 free(ppipe->buffer); 485 AFREE(ppipe); 486 } 487 488 static int 489 pingPongPipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers ) 490 { 491 PingPongPipe* pipe = opaque; 492 int ret = 0; 493 int count; 494 const GoldfishPipeBuffer* buff = buffers; 495 const GoldfishPipeBuffer* buffEnd = buff + numBuffers; 496 497 count = 0; 498 for ( ; buff < buffEnd; buff++ ) 499 count += buff->size; 500 501 /* Do we need to grow the pingpong buffer? */ 502 while (count > pipe->size - pipe->count) { 503 size_t newsize = pipe->size*2; 504 uint8_t* newbuff = realloc(pipe->buffer, newsize); 505 int wpos = pipe->pos + pipe->count; 506 if (newbuff == NULL) { 507 break; 508 } 509 if (wpos > pipe->size) { 510 wpos -= pipe->size; 511 memcpy(newbuff + pipe->size, newbuff, wpos); 512 } 513 pipe->buffer = newbuff; 514 pipe->size = newsize; 515 D("pingpong buffer is now %d bytes", newsize); 516 } 517 518 for ( buff = buffers; buff < buffEnd; buff++ ) { 519 int avail = pipe->size - pipe->count; 520 if (avail <= 0) { 521 if (ret == 0) 522 ret = PIPE_ERROR_AGAIN; 523 break; 524 } 525 if (avail > buff->size) { 526 avail = buff->size; 527 } 528 529 int wpos = pipe->pos + pipe->count; 530 if (wpos >= pipe->size) { 531 wpos -= pipe->size; 532 } 533 if (wpos + avail <= pipe->size) { 534 memcpy(pipe->buffer + wpos, buff->data, avail); 535 } else { 536 int avail2 = pipe->size - wpos; 537 memcpy(pipe->buffer + wpos, buff->data, avail2); 538 memcpy(pipe->buffer, buff->data + avail2, avail - avail2); 539 } 540 pipe->count += avail; 541 ret += avail; 542 } 543 544 /* Wake up any waiting readers if we wrote something */ 545 if (pipe->count > 0 && (pipe->flags & PIPE_WAKE_READ)) { 546 goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_READ); 547 } 548 549 return ret; 550 } 551 552 static int 553 pingPongPipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers ) 554 { 555 PingPongPipe* pipe = opaque; 556 int ret = 0; 557 558 while (numBuffers > 0) { 559 int avail = pipe->count; 560 if (avail <= 0) { 561 if (ret == 0) 562 ret = PIPE_ERROR_AGAIN; 563 break; 564 } 565 if (avail > buffers[0].size) { 566 avail = buffers[0].size; 567 } 568 569 int rpos = pipe->pos; 570 571 if (rpos + avail <= pipe->size) { 572 memcpy(buffers[0].data, pipe->buffer + rpos, avail); 573 } else { 574 int avail2 = pipe->size - rpos; 575 memcpy(buffers[0].data, pipe->buffer + rpos, avail2); 576 memcpy(buffers[0].data + avail2, pipe->buffer, avail - avail2); 577 } 578 pipe->count -= avail; 579 pipe->pos += avail; 580 if (pipe->pos >= pipe->size) { 581 pipe->pos -= pipe->size; 582 } 583 ret += avail; 584 numBuffers--; 585 buffers++; 586 } 587 588 /* Wake up any waiting readers if we wrote something */ 589 if (pipe->count < PINGPONG_SIZE && (pipe->flags & PIPE_WAKE_WRITE)) { 590 goldfish_pipe_wake(pipe->hwpipe, PIPE_WAKE_WRITE); 591 } 592 593 return ret; 594 } 595 596 static unsigned 597 pingPongPipe_poll( void* opaque ) 598 { 599 PingPongPipe* pipe = opaque; 600 unsigned ret = 0; 601 602 if (pipe->count < pipe->size) 603 ret |= PIPE_POLL_OUT; 604 605 if (pipe->count > 0) 606 ret |= PIPE_POLL_IN; 607 608 return ret; 609 } 610 611 static void 612 pingPongPipe_wakeOn( void* opaque, int flags ) 613 { 614 PingPongPipe* pipe = opaque; 615 pipe->flags |= (unsigned)flags; 616 } 617 618 static const GoldfishPipeFuncs pingPongPipe_funcs = { 619 pingPongPipe_init, 620 pingPongPipe_close, 621 pingPongPipe_sendBuffers, 622 pingPongPipe_recvBuffers, 623 pingPongPipe_poll, 624 pingPongPipe_wakeOn, 625 }; 626 627 #endif /* DEBUG_PINGPONG_PIPE */ 628 629 /*********************************************************************** 630 *********************************************************************** 631 ***** 632 ***** T H R O T T L E P I P E S 633 ***** 634 *****/ 635 636 /* Similar to PingPongPipe, but will throttle the bandwidth to test 637 * blocking I/O. 638 */ 639 640 #ifdef DEBUG_THROTTLE_PIPE 641 642 typedef struct { 643 PingPongPipe pingpong; 644 double sendRate; 645 int64_t sendExpiration; 646 double recvRate; 647 int64_t recvExpiration; 648 QEMUTimer* timer; 649 } ThrottlePipe; 650 651 /* forward declaration */ 652 static void throttlePipe_timerFunc( void* opaque ); 653 654 static void* 655 throttlePipe_init( void* hwpipe, void* svcOpaque, const char* args ) 656 { 657 ThrottlePipe* pipe; 658 659 ANEW0(pipe); 660 pingPongPipe_init0(&pipe->pingpong, hwpipe, svcOpaque); 661 pipe->timer = qemu_new_timer_ns(vm_clock, throttlePipe_timerFunc, pipe); 662 /* For now, limit to 500 KB/s in both directions */ 663 pipe->sendRate = 1e9 / (500*1024*8); 664 pipe->recvRate = pipe->sendRate; 665 return pipe; 666 } 667 668 static void 669 throttlePipe_close( void* opaque ) 670 { 671 ThrottlePipe* pipe = opaque; 672 673 qemu_del_timer(pipe->timer); 674 qemu_free_timer(pipe->timer); 675 pingPongPipe_close(&pipe->pingpong); 676 } 677 678 static void 679 throttlePipe_rearm( ThrottlePipe* pipe ) 680 { 681 int64_t minExpiration = 0; 682 683 DD("%s: sendExpiration=%lld recvExpiration=%lld\n", __FUNCTION__, pipe->sendExpiration, pipe->recvExpiration); 684 685 if (pipe->sendExpiration) { 686 if (minExpiration == 0 || pipe->sendExpiration < minExpiration) 687 minExpiration = pipe->sendExpiration; 688 } 689 690 if (pipe->recvExpiration) { 691 if (minExpiration == 0 || pipe->recvExpiration < minExpiration) 692 minExpiration = pipe->recvExpiration; 693 } 694 695 if (minExpiration != 0) { 696 DD("%s: Arming for %lld\n", __FUNCTION__, minExpiration); 697 qemu_mod_timer(pipe->timer, minExpiration); 698 } 699 } 700 701 static void 702 throttlePipe_timerFunc( void* opaque ) 703 { 704 ThrottlePipe* pipe = opaque; 705 int64_t now = qemu_get_clock_ns(vm_clock); 706 707 DD("%s: TICK! now=%lld sendExpiration=%lld recvExpiration=%lld\n", 708 __FUNCTION__, now, pipe->sendExpiration, pipe->recvExpiration); 709 710 /* Timer has expired, signal wake up if needed */ 711 int flags = 0; 712 713 if (pipe->sendExpiration && now > pipe->sendExpiration) { 714 flags |= PIPE_WAKE_WRITE; 715 pipe->sendExpiration = 0; 716 } 717 if (pipe->recvExpiration && now > pipe->recvExpiration) { 718 flags |= PIPE_WAKE_READ; 719 pipe->recvExpiration = 0; 720 } 721 flags &= pipe->pingpong.flags; 722 if (flags != 0) { 723 DD("%s: WAKE %d\n", __FUNCTION__, flags); 724 goldfish_pipe_wake(pipe->pingpong.hwpipe, flags); 725 } 726 727 throttlePipe_rearm(pipe); 728 } 729 730 static int 731 throttlePipe_sendBuffers( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers ) 732 { 733 ThrottlePipe* pipe = opaque; 734 int ret; 735 736 if (pipe->sendExpiration > 0) { 737 return PIPE_ERROR_AGAIN; 738 } 739 740 ret = pingPongPipe_sendBuffers(&pipe->pingpong, buffers, numBuffers); 741 if (ret > 0) { 742 /* Compute next send expiration time */ 743 pipe->sendExpiration = qemu_get_clock_ns(vm_clock) + ret*pipe->sendRate; 744 throttlePipe_rearm(pipe); 745 } 746 return ret; 747 } 748 749 static int 750 throttlePipe_recvBuffers( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers ) 751 { 752 ThrottlePipe* pipe = opaque; 753 int ret; 754 755 if (pipe->recvExpiration > 0) { 756 return PIPE_ERROR_AGAIN; 757 } 758 759 ret = pingPongPipe_recvBuffers(&pipe->pingpong, buffers, numBuffers); 760 if (ret > 0) { 761 pipe->recvExpiration = qemu_get_clock_ns(vm_clock) + ret*pipe->recvRate; 762 throttlePipe_rearm(pipe); 763 } 764 return ret; 765 } 766 767 static unsigned 768 throttlePipe_poll( void* opaque ) 769 { 770 ThrottlePipe* pipe = opaque; 771 unsigned ret = pingPongPipe_poll(&pipe->pingpong); 772 773 if (pipe->sendExpiration > 0) 774 ret &= ~PIPE_POLL_OUT; 775 776 if (pipe->recvExpiration > 0) 777 ret &= ~PIPE_POLL_IN; 778 779 return ret; 780 } 781 782 static void 783 throttlePipe_wakeOn( void* opaque, int flags ) 784 { 785 ThrottlePipe* pipe = opaque; 786 pingPongPipe_wakeOn(&pipe->pingpong, flags); 787 } 788 789 static const GoldfishPipeFuncs throttlePipe_funcs = { 790 throttlePipe_init, 791 throttlePipe_close, 792 throttlePipe_sendBuffers, 793 throttlePipe_recvBuffers, 794 throttlePipe_poll, 795 throttlePipe_wakeOn, 796 }; 797 798 #endif /* DEBUG_THROTTLE_PIPE */ 799 800 /*********************************************************************** 801 *********************************************************************** 802 ***** 803 ***** G O L D F I S H P I P E D E V I C E 804 ***** 805 *****/ 806 807 struct PipeDevice { 808 struct goldfish_device dev; 809 810 /* the list of all pipes */ 811 Pipe* pipes; 812 813 /* the list of signalled pipes */ 814 Pipe* signaled_pipes; 815 816 /* i/o registers */ 817 uint32_t address; 818 uint32_t size; 819 uint32_t status; 820 uint32_t channel; 821 uint32_t wakes; 822 }; 823 824 825 static void 826 pipeDevice_doCommand( PipeDevice* dev, uint32_t command ) 827 { 828 Pipe** lookup = pipe_list_findp_channel(&dev->pipes, dev->channel); 829 Pipe* pipe = *lookup; 830 CPUState* env = cpu_single_env; 831 832 /* Check that we're referring a known pipe channel */ 833 if (command != PIPE_CMD_OPEN && pipe == NULL) { 834 dev->status = PIPE_ERROR_INVAL; 835 return; 836 } 837 838 /* If the pipe is closed by the host, return an error */ 839 if (pipe != NULL && pipe->closed && command != PIPE_CMD_CLOSE) { 840 dev->status = PIPE_ERROR_IO; 841 return; 842 } 843 844 switch (command) { 845 case PIPE_CMD_OPEN: 846 DD("%s: CMD_OPEN channel=0x%x", __FUNCTION__, dev->channel); 847 if (pipe != NULL) { 848 dev->status = PIPE_ERROR_INVAL; 849 break; 850 } 851 pipe = pipe_new(dev->channel, dev); 852 pipe->next = dev->pipes; 853 dev->pipes = pipe; 854 dev->status = 0; 855 break; 856 857 case PIPE_CMD_CLOSE: 858 DD("%s: CMD_CLOSE channel=0x%x", __FUNCTION__, dev->channel); 859 /* Remove from device's lists */ 860 *lookup = pipe->next; 861 pipe->next = NULL; 862 pipe_list_remove_waked(&dev->signaled_pipes, pipe); 863 /* Call close callback */ 864 if (pipe->funcs->close) { 865 pipe->funcs->close(pipe->opaque); 866 } 867 /* Free stuff */ 868 AFREE(pipe); 869 break; 870 871 case PIPE_CMD_POLL: 872 dev->status = pipe->funcs->poll(pipe->opaque); 873 DD("%s: CMD_POLL > status=%d", __FUNCTION__, dev->status); 874 break; 875 876 case PIPE_CMD_READ_BUFFER: { 877 /* Translate virtual address into physical one, into emulator memory. */ 878 GoldfishPipeBuffer buffer; 879 uint32_t address = dev->address; 880 uint32_t page = address & TARGET_PAGE_MASK; 881 target_phys_addr_t phys; 882 #ifdef CONFIG_KVM 883 if(kvm_enabled()) { 884 cpu_synchronize_state(env, 0); 885 } 886 #endif 887 phys = cpu_get_phys_page_debug(env, page); 888 buffer.data = qemu_get_ram_ptr(phys) + (address - page); 889 buffer.size = dev->size; 890 dev->status = pipe->funcs->recvBuffers(pipe->opaque, &buffer, 1); 891 DD("%s: CMD_READ_BUFFER channel=0x%x address=0x%08x size=%d > status=%d", 892 __FUNCTION__, dev->channel, dev->address, dev->size, dev->status); 893 break; 894 } 895 896 case PIPE_CMD_WRITE_BUFFER: { 897 /* Translate virtual address into physical one, into emulator memory. */ 898 GoldfishPipeBuffer buffer; 899 uint32_t address = dev->address; 900 uint32_t page = address & TARGET_PAGE_MASK; 901 target_phys_addr_t phys; 902 #ifdef CONFIG_KVM 903 if(kvm_enabled()) { 904 cpu_synchronize_state(env, 0); 905 } 906 #endif 907 phys = cpu_get_phys_page_debug(env, page); 908 buffer.data = qemu_get_ram_ptr(phys) + (address - page); 909 buffer.size = dev->size; 910 dev->status = pipe->funcs->sendBuffers(pipe->opaque, &buffer, 1); 911 DD("%s: CMD_WRITE_BUFFER channel=0x%x address=0x%08x size=%d > status=%d", 912 __FUNCTION__, dev->channel, dev->address, dev->size, dev->status); 913 break; 914 } 915 916 case PIPE_CMD_WAKE_ON_READ: 917 DD("%s: CMD_WAKE_ON_READ channel=0x%x", __FUNCTION__, dev->channel); 918 if ((pipe->wanted & PIPE_WAKE_READ) == 0) { 919 pipe->wanted |= PIPE_WAKE_READ; 920 pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); 921 } 922 dev->status = 0; 923 break; 924 925 case PIPE_CMD_WAKE_ON_WRITE: 926 DD("%s: CMD_WAKE_ON_WRITE channel=0x%x", __FUNCTION__, dev->channel); 927 if ((pipe->wanted & PIPE_WAKE_WRITE) == 0) { 928 pipe->wanted |= PIPE_WAKE_WRITE; 929 pipe->funcs->wakeOn(pipe->opaque, pipe->wanted); 930 } 931 dev->status = 0; 932 break; 933 934 default: 935 D("%s: command=%d (0x%x)\n", __FUNCTION__, command, command); 936 } 937 } 938 939 static void pipe_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) 940 { 941 PipeDevice *s = (PipeDevice *)opaque; 942 943 switch (offset) { 944 case PIPE_REG_COMMAND: 945 DR("%s: command=%d (0x%x)", __FUNCTION__, value, value); 946 pipeDevice_doCommand(s, value); 947 break; 948 949 case PIPE_REG_SIZE: 950 DR("%s: size=%d (0x%x)", __FUNCTION__, value, value); 951 s->size = value; 952 break; 953 954 case PIPE_REG_ADDRESS: 955 DR("%s: address=%d (0x%x)", __FUNCTION__, value, value); 956 s->address = value; 957 break; 958 959 case PIPE_REG_CHANNEL: 960 DR("%s: channel=%d (0x%x)", __FUNCTION__, value, value); 961 s->channel = value; 962 break; 963 964 default: 965 D("%s: offset=%d (0x%x) value=%d (0x%x)\n", __FUNCTION__, offset, 966 offset, value, value); 967 break; 968 } 969 } 970 971 /* I/O read */ 972 static uint32_t pipe_dev_read(void *opaque, target_phys_addr_t offset) 973 { 974 PipeDevice *dev = (PipeDevice *)opaque; 975 976 switch (offset) { 977 case PIPE_REG_STATUS: 978 DR("%s: REG_STATUS status=%d (0x%x)", __FUNCTION__, dev->status, dev->status); 979 return dev->status; 980 981 case PIPE_REG_CHANNEL: 982 if (dev->signaled_pipes != NULL) { 983 Pipe* pipe = dev->signaled_pipes; 984 DR("%s: channel=0x%x wanted=%d", __FUNCTION__, 985 pipe->channel, pipe->wanted); 986 dev->wakes = pipe->wanted; 987 pipe->wanted = 0; 988 dev->signaled_pipes = pipe->next_waked; 989 pipe->next_waked = NULL; 990 if (dev->signaled_pipes == NULL) { 991 goldfish_device_set_irq(&dev->dev, 0, 0); 992 DD("%s: lowering IRQ", __FUNCTION__); 993 } 994 return pipe->channel; 995 } 996 DR("%s: no signaled channels", __FUNCTION__); 997 return 0; 998 999 case PIPE_REG_WAKES: 1000 DR("%s: wakes %d", __FUNCTION__, dev->wakes); 1001 return dev->wakes; 1002 1003 default: 1004 D("%s: offset=%d (0x%x)\n", __FUNCTION__, offset, offset); 1005 } 1006 return 0; 1007 } 1008 1009 static CPUReadMemoryFunc *pipe_dev_readfn[] = { 1010 pipe_dev_read, 1011 pipe_dev_read, 1012 pipe_dev_read 1013 }; 1014 1015 static CPUWriteMemoryFunc *pipe_dev_writefn[] = { 1016 pipe_dev_write, 1017 pipe_dev_write, 1018 pipe_dev_write 1019 }; 1020 1021 /* initialize the trace device */ 1022 void pipe_dev_init() 1023 { 1024 PipeDevice *s; 1025 1026 s = (PipeDevice *) qemu_mallocz(sizeof(*s)); 1027 1028 s->dev.name = "qemu_pipe"; 1029 s->dev.id = -1; 1030 s->dev.base = 0; // will be allocated dynamically 1031 s->dev.size = 0x2000; 1032 s->dev.irq = 0; 1033 s->dev.irq_count = 1; 1034 1035 goldfish_device_add(&s->dev, pipe_dev_readfn, pipe_dev_writefn, s); 1036 1037 #if DEBUG_ZERO_PIPE 1038 goldfish_pipe_add_type("zero", NULL, &zeroPipe_funcs); 1039 #endif 1040 #if DEBUG_PINGPONG_PIPE 1041 goldfish_pipe_add_type("pingpong", NULL, &pingPongPipe_funcs); 1042 #endif 1043 #if DEBUG_THROTTLE_PIPE 1044 goldfish_pipe_add_type("throttle", NULL, &throttlePipe_funcs); 1045 #endif 1046 } 1047 1048 void 1049 goldfish_pipe_wake( void* hwpipe, unsigned flags ) 1050 { 1051 Pipe* pipe = hwpipe; 1052 Pipe** lookup; 1053 PipeDevice* dev = pipe->device; 1054 1055 DD("%s: channel=0x%x flags=%d", __FUNCTION__, pipe->channel, flags); 1056 1057 /* If not already there, add to the list of signaled pipes */ 1058 lookup = pipe_list_findp_waked(&dev->signaled_pipes, pipe); 1059 if (!*lookup) { 1060 pipe->next_waked = dev->signaled_pipes; 1061 dev->signaled_pipes = pipe; 1062 } 1063 pipe->wanted |= (unsigned)flags; 1064 1065 /* Raise IRQ to indicate there are items on our list ! */ 1066 goldfish_device_set_irq(&dev->dev, 0, 1); 1067 DD("%s: raising IRQ", __FUNCTION__); 1068 } 1069 1070 void 1071 goldfish_pipe_close( void* hwpipe ) 1072 { 1073 Pipe* pipe = hwpipe; 1074 1075 D("%s: channel=0x%x (closed=%d)", __FUNCTION__, pipe->channel, pipe->closed); 1076 1077 if (!pipe->closed) { 1078 pipe->closed = 1; 1079 goldfish_pipe_wake( hwpipe, PIPE_WAKE_CLOSED ); 1080 } 1081 } 1082