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