• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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