Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup of locking in host device interface
[palacios.git] / linux_module / iface-host-dev.c
1 /* 
2  * Host device interface + user-space device interface
3  * (c) 2011 Peter Dinda
4  */
5
6 #include <linux/device.h>
7 #include <linux/cdev.h>
8 #include <linux/errno.h>
9 #include <linux/fs.h>
10 #include <linux/uaccess.h>
11 #include <linux/poll.h>
12 #include <linux/anon_inodes.h>
13 #include <linux/file.h>
14 #include <linux/sched.h>
15 #include <linux/delay.h>
16
17 #include <interfaces/vmm_host_dev.h>
18
19 #include "palacios.h"
20 #include "iface-host-dev.h"
21 #include "linux-exts.h"
22 #include "vm.h"
23
24 /*
25   There are two things in this file:
26
27
28   1. An implementation of the Palacios host device interface that will
29      accept any URL from Palacios.  Currently, the only URL type it will
30      handle is user:<name>, but it should be clear how to extend with
31      other types.
32
33      Palacios opens a host device by issuing something like this:
34
35          palacios_host_dev_open( impl="user:foo" busclass=pci, opaque )
36
37      This will attempt to rendezvous with the user space device The
38      rendevzous retry and timeout periods can be set below.
39
40   2. An implementation of user: urls - the host interface is mapped
41      into an RPC-like interface to/from user space via a file
42      interface.   
43
44      The user space gets a file descriptor like this:
45
46      int vmfd = open("/dev/v3-vmX",...);
47
48      int devfd = ioctl(vmfd,V3_HOST_DEV_CONNECT,"user:foo"); 
49
50      This will attempt to rendezvous with the host side.
51
52      If it returns successfully, you can now issue synchronous,
53      blocking RPCs to the guest to read/write its memory and inject
54      irqs.  This means that a user->host request is handled
55      immediately, and independently of any host->user request. 
56
57      struct palacios_host_dev_user_op op;
58
59      // fill out op
60      op.type = PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST; 
61      ...
62
63      ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL, &op);
64
65      // return value is # bytes read or written; or 0 if irq injected
66      // negative value is error
67
68      The interface from the host to the user side is asynchronous
69      blocking RPC.  Any host device will have at most one outstanding
70      request from palacios.  The implementation here stores the
71      request until the user side is ready to accept it.  The user side
72      can check if there is a request via a poll/select or an ioctl.
73      The ioctl also returns the needed size for the request structure.
74      After the user side has a request, it is expected to process it,
75      perhaps making user->host requests as described above, and then
76      return a response.  Only one host->user request should be in
77      progress at any time in the user space.
78
79      What this looks like is:
80      
81      poll(...devfd for read...) or select(...devfd for read...)
82
83      if (devfd is marked readable) { 
84          uint64_t size;
85
86          ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&size);
87          // returns 1 if there is a request, 0 if not, negative on err
88
89          struct palacios_host_dev_host_request_response *req;
90
91          req = allocate req to be at least size bytes long
92
93          ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL,req)
94          // returns 1 if there is a request, 0 if not, negative on err
95          
96          // process request, perhaps using above user->host request
97          // build response structure
98          // resp.data_len == size of structure including relevant data at end
99
100          ioctl(devfd,V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL,resp);
101          // returns 0 if there is no outstanding request (user error)
102          // 1 on success, negative on error
103      }
104     
105      Note that the current model has deferred rendezvous and allows
106      for user-side device disconnection and reconnection.  It is important
107      to note that this implementation does NOT deal with state discrepency
108      between the palacios-side and the user-side.   For example, a user-side
109      device can disconnect, a palacios-side request can then fail, and 
110      when the user-side device reconnects, it is unaware of this failure.  
111
112 */
113
114
115 struct palacios_host_dev {
116     spinlock_t      lock;
117     struct list_head devs;
118 };
119
120
121 #define MAX_URL 256
122
123 #define RENDEZVOUS_WAIT_SECS  60
124 #define RENDEZVOUS_RETRY_SECS 1
125
126 #define DEEP_DEBUG    0
127 #define SHALLOW_DEBUG 0
128
129 #if DEEP_DEBUG == 1
130 #define DEEP_DEBUG_PRINT(fmt, args...) DEBUG(fmt, ##args)
131 #else
132 #define DEEP_DEBUG_PRINT(fmt, args...) 
133 #endif
134
135 #if SHALLOW_DEBUG == 1
136 #define SHALLOW_DEBUG_PRINT(fmt, args...) INFO(fmt, ##args)
137 #else
138 #define SHALLOW_DEBUG_PRINT(fmt, args...) 
139 #endif
140
141
142 struct palacios_host_device_user {
143     spinlock_t lock;
144     int      connected;    // is the user space connected to this?
145     int      waiting;      // am I waiting for a user-space response?
146
147     int      fd;           // what is the user space fd?
148
149     char     url[MAX_URL]; // what is the url describing the device
150
151     v3_guest_dev_t guestdev; // what is the palacios-side device
152     v3_guest_dev_intr_t guestintr; // what is the palacios-side device interrupt info
153
154     wait_queue_head_t  user_wait_queue; // user space processes waiting on us (should be only one)
155     wait_queue_head_t  host_wait_queue; // host threads (should only be one) waiting on user space
156
157     struct v3_guest                                *guest; // my guest
158     struct palacios_host_dev_host_request_response *req;   // curent request
159     struct palacios_host_dev_host_request_response *resp;  // curent response
160
161     struct list_head  node;   // for adding me to the list of hostdevs this VM has
162 };
163
164
165 /**************************************************************************************
166   Utility functions
167 *************************************************************************************/
168
169 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
170 {
171     if (dev->req) {
172         palacios_free(dev->req);
173         dev->req=0;
174     } 
175     if (dev->resp) { 
176         palacios_free(dev->resp);
177         dev->resp=0;
178     }
179     palacios_free(dev);
180 }
181
182
183 //
184 // Is this structure big enough for the data_size we will use?
185 //
186 // THIS FUNCTION CAN BE CALLED WHILE INTERRUPTS ARE OFF
187 //
188 static int palacios_bigenough_reqresp(struct palacios_host_dev_host_request_response *r, uint64_t data_size)
189 {
190     if (!r) { 
191         return 0;
192     } else {
193         if (((r->len)-sizeof(struct palacios_host_dev_host_request_response)) < data_size) {
194             return 0;
195         } else {
196             return 1;
197         }
198     }
199 }
200
201 //
202 // Resize a request/response structure so that it will fit data_size bytes
203 //
204 // At the end of this, *r->len >= sizeof(struct)+data_size
205 //
206 // THIS FUNCTION MAY SLEEP AS IT CALLS KMALLOC 
207 // DO NOT CALL IT WHILE HOLDING A SPIN LOCK WITH INTERRUPTS OFF
208 //
209 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
210 {
211     
212     DEEP_DEBUG_PRINT("palacios: hostdev: resize 0x%p to %llu\n",*r,data_size);
213
214     if ((*r)==0) { 
215         // allocate it
216         DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n");
217         *r = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size);
218         DEEP_DEBUG_PRINT("palacios: hostdev: palacios_alloc done\n");
219         if ((*r)==0) { 
220             ERROR("palacios: hostdev: failed to allocate\n");
221             return -1;
222         } else {
223             (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
224             DEEP_DEBUG_PRINT("palacios: hostdev: allocated\n");
225             return 0;
226         }
227     } else {
228         //let it go if it's big enough
229         uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
230
231         if (data_size<=cur_len) { 
232             // do nothing
233             DEEP_DEBUG_PRINT("palacios: hostdev: size ok\n");
234             return 0;
235         } else {
236             struct palacios_host_dev_host_request_response *new;
237
238             if (!copy) { 
239                 palacios_free(*r);
240                 *r=0;
241             }
242             new = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size);
243             if (!new) { 
244                 ERROR("palacios: hostdev: failed to reallocate\n");
245                 return -1;
246             } else {
247                 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
248                 if (copy) { 
249                     memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
250                     new->data_len=(*r)->data_len;
251                     palacios_free(*r);
252                 }
253                 *r=new;
254                 DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n");
255                 return 0;
256             }
257         }
258     }
259 }
260
261 static void cycle_request_response(struct palacios_host_device_user *dev)
262 {
263     DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response\n");
264     // wake up user side so that polls fall through
265     wake_up_interruptible(&(dev->user_wait_queue));
266     // put us to sleep until the user side wakes us up
267     while (wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0)) != 0) {}
268
269     DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response - done\n");
270 }
271
272 static void cycle_response_request(struct palacios_host_device_user *dev)
273 {
274     DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request\n");
275     // wake up host side
276     wake_up_interruptible(&(dev->host_wait_queue));
277     DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request - done\n");
278 }
279
280     
281 /*********************************************************************************************
282
283     Interface to user space
284
285  *********************************************************************************************/ 
286
287
288
289 static unsigned int host_dev_poll(struct file * filp, 
290                                   struct poll_table_struct * poll_tb) 
291 {
292
293     struct palacios_host_device_user * dev = filp->private_data;
294     unsigned long f;
295
296     SHALLOW_DEBUG_PRINT("palacios: hostdev: poll\n");
297
298     if (!dev->connected) { 
299         ERROR("palcios: hostdev: poll on unconnected device\n");
300         return -EFAULT;
301     }
302
303     palacios_spinlock_lock_irqsave(&(dev->lock),f);
304
305
306     // register ourselves on the user wait queue
307     poll_wait(filp, &(dev->user_wait_queue), poll_tb);
308
309     if (dev->waiting) { 
310         // Yes, we have a request if you want it!
311         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
312         DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n");
313         return  POLLIN | POLLRDNORM;
314     } 
315
316     // No request yet, so we need to wait for one to show up.
317
318     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
319
320     DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
321     // We will get called again when that queue is woken up
322
323     return 0;
324 }
325
326
327 static int host_dev_release(struct inode * i, struct file * filp) 
328 {
329     struct palacios_host_device_user *dev = filp->private_data;
330     unsigned long f;
331
332     INFO("palacios: user side is closing host device \"%s\"\n",dev->url);
333     
334     palacios_spinlock_lock_irqsave(&(dev->lock), f);
335     dev->connected = 0;
336     palacios_spinlock_unlock_irqrestore(&(dev->lock), f);
337
338     // it is the palacios->host interface's responsibility to ignore
339     // reads/writes until connected is true
340
341     return 0;
342 }
343
344 static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg)
345 {
346     void __user *argp = (void __user *)arg;
347
348     struct palacios_host_device_user *dev = fp->private_data;
349
350     DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
351     
352
353     if (!dev->connected) { 
354         ERROR("palacios: hostdev: ioctl on unconnected device\n");
355         return -EFAULT;
356     }
357     
358     switch (val) { 
359         case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
360             
361             struct palacios_host_dev_user_op op;
362             
363             if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) { 
364                 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
365                 return -EFAULT;
366             }
367
368             DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
369             
370             switch (op.type) { 
371                 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
372                     void *temp = palacios_alloc(op.len);
373
374                     DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
375
376                     if (!temp) { 
377                         ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
378                         return -EFAULT;
379                     }
380                     
381                     if (v3_host_dev_read_guest_mem(dev,
382                                                    dev->guestdev,
383                                                    op.gpa,
384                                                    temp,
385                                                    op.len) != op.len) {
386                         ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
387                         palacios_free(temp);
388                         return -EFAULT;
389                     }
390                     
391                     if (copy_to_user(op.data,temp,op.len)) { 
392                         ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
393                         palacios_free(temp);
394                         return -EFAULT;
395                     }
396
397                     palacios_free(temp);
398
399                     return op.len;
400                 }
401                     break;
402                     
403
404                 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
405                     void *temp;
406                     
407                     DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
408
409                     temp = palacios_alloc(op.len);
410
411                     if (!temp) { 
412                         ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
413                         return -EFAULT;
414                     }
415                     
416                     if (copy_from_user(temp,op.data,op.len)) { 
417                         ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
418                         palacios_free(temp);
419                         return -EFAULT;
420                     }
421                     
422                     if (v3_host_dev_write_guest_mem(dev,
423                                                     dev->guestdev,
424                                                     op.gpa,
425                                                     temp,
426                                                     op.len) != op.len) {
427                         ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
428                         palacios_free(temp);
429                         return -EFAULT;
430                     }
431
432                     palacios_free(temp);
433                     
434                     return op.len;
435                 }
436                     break;
437
438                 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_RAISE_GUEST: {
439
440                     DEEP_DEBUG_PRINT("palacios: hostdev: irq raise guest\n");
441
442                     return  v3_host_dev_raise_irq(dev, dev->guestdev, dev->guestintr, op.irq);
443                 }
444                     break;
445                 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_LOWER_GUEST: {
446
447                     DEEP_DEBUG_PRINT("palacios: hostdev: irq lower guest\n");
448
449                     return  v3_host_dev_lower_irq(dev, dev->guestdev, dev->guestintr, op.irq);
450                 }
451                     break;
452
453                 default:
454                     ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
455                     return -EFAULT;
456                     break;
457             }
458         }
459             break;
460
461         case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
462             
463             unsigned long f;
464
465
466             DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
467             
468             palacios_spinlock_lock_irqsave(&(dev->lock),f);
469             
470             if (!(dev->waiting)) { 
471                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
472                 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
473                 schedule();  // avoid livelock for polling user space process  SUSPICOUS
474                 return 0; // no request available now
475             } 
476
477             // safe to unlock here since if we are in the waiting state
478             // the palacios side will not modify the request
479             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
480
481             if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) { 
482                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
483                 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
484                 return -EFAULT; // failed to copy!
485
486             }
487             
488             DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
489
490             return 1; // have request for you
491             
492         }
493             
494             break;
495             
496         case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
497             
498             unsigned long f;
499             
500             palacios_spinlock_lock_irqsave(&(dev->lock),f);
501             
502             DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
503
504             if (!(dev->waiting) || !(dev->req)) { 
505                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
506                 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
507                 return 0; // no request available now
508             } 
509
510             // Safe to unlock here since if we are in the waiting 
511             // state, the request will not be modified by the palacios side
512             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
513             
514             if (copy_to_user(argp,dev->req,dev->req->data_len)) { 
515                 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
516                 return -EFAULT; // failed to copy!
517             }
518     
519             DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
520             
521             return 1; // copied request for you
522         }
523             break;
524             
525         case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
526
527             unsigned long f;
528             uint64_t user_datalen;
529             uint64_t old_len;
530             
531             palacios_spinlock_lock_irqsave(&(dev->lock),f);
532             
533             DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
534
535             if (!(dev->waiting)) { 
536                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
537                 ERROR("palacios: hostdev: no matching request for pushed response\n");
538                 return 0; // no request outstanding, so we do not need a response!
539             }
540             
541             // Safe to unlock here as the palacios side will not
542             // modify the request or copy the response until we
543             // reset dev->waiting
544             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
545
546             if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) { 
547                 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
548                 return -EFAULT; // failed to copy!
549             } 
550
551             if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) { 
552                 // bad user
553                 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
554                 return -EFAULT;
555             }
556
557             if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
558                 // not enough room.
559                 DEEP_DEBUG_PRINT("palacios: response not big enough, resizing on device \"%s\"\n",dev->url);
560
561                 
562                 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
563                     ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
564                     return -EFAULT;
565                 } 
566             }
567
568             //We only copy data_len bytes from user, but we will
569             //overwrite the len field, so we preserve and then restore
570             old_len = dev->resp->len;
571             if (copy_from_user(dev->resp, argp, user_datalen)) { 
572                 dev->resp->len=old_len;
573                 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
574                 return -EFAULT; // failed to copy!
575             } 
576             dev->resp->len=old_len;
577             
578             DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
579             // now have valid response!
580             dev->waiting=0;
581
582             // wake the palacios side up so that it sees it
583             cycle_response_request(dev);
584
585             return 1; // done
586         }
587             break;
588             
589         default:
590             ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
591             return -EFAULT;
592             break;
593     }
594     
595 }
596
597 static struct file_operations host_dev_fops = {
598     .poll     = host_dev_poll,
599     .release  = host_dev_release,
600     .compat_ioctl = host_dev_ioctl,
601     .unlocked_ioctl = host_dev_ioctl,
602 };
603
604
605
606 static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) 
607 {
608     void __user * argp = (void __user *)arg;
609     char url[MAX_URL];
610     struct palacios_host_dev * host_dev = priv_data;
611     struct palacios_host_device_user *dev;
612     unsigned long f1, f2;
613     int i;
614
615
616
617     if (copy_from_user(url, argp, MAX_URL)) {
618         ERROR("copy from user error getting url for host device connect...\n");
619         return -EFAULT;
620     }
621
622     // currently only support user: types:
623     if (strncasecmp(url,"user:",5)) { 
624         ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
625         return -1;
626     }
627     
628     INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
629     
630     // We will scan the list looking for the relevant
631     // URL.  If we don't find it after a while, we give up
632     
633     for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
634         palacios_spinlock_lock_irqsave(&(host_dev->lock),f1);
635         list_for_each_entry(dev,&(host_dev->devs), node) {
636             if (!strncasecmp(url,dev->url,MAX_URL)) { 
637                 // found it
638                 palacios_spinlock_lock_irqsave(&(dev->lock),f2);
639                 if (dev->connected) { 
640                     ERROR("palacios: device for \"%s\" is already connected!\n",url);
641                     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
642                     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
643                     return -1;
644                 } else {
645                     dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
646                     if (dev->fd<0) { 
647                         ERROR("palacios: cannot create fd for device \"%s\"\n",url);
648                         palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
649                         palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
650                         return -1;
651                     }
652                     dev->connected=1;
653                     dev->waiting=0;
654                     if (dev->req) { 
655                         palacios_free(dev->req);
656                         dev->req=0;
657                     } 
658                     if (dev->resp) { 
659                         palacios_free(dev->resp);
660                         dev->resp=0;
661                     }
662                     INFO("palacios: connected fd for device \"%s\"\n",url);
663                     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
664                     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
665                     return dev->fd;
666                 }
667                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
668             }
669         }
670         palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
671         
672         ssleep(RENDEZVOUS_RETRY_SECS);
673     }
674     
675     ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
676     
677     return -1;
678     
679 }
680
681
682
683
684
685
686
687
688 /***************************************************************************************
689
690    Following this is the implementation of the palacios->host interface
691
692 **************************************************************************************/
693
694
695 /* Attempt to rendezvous with the user device if no device is currently connected */
696 static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
697 {
698     unsigned long f;
699     int i;
700
701     if (dev->connected) { 
702         return 0;
703     }
704
705    
706     INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
707
708     // Now wait until we are noticed!
709     for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
710         palacios_spinlock_lock_irqsave(&(dev->lock),f);
711         if (dev->connected) { 
712             INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
713             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
714             return 0;
715         }
716         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
717         ssleep(RENDEZVOUS_RETRY_SECS);
718     }
719     
720     ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
721
722     // We stay in the list because a future rendezvous might happen
723     
724     return -1;
725 }
726
727
728 /* Creates the device without rendezvous */
729 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
730                                                      v3_bus_class_t bus,
731                                                      v3_guest_dev_t gdev,
732                                                      v3_guest_dev_intr_t gintr,
733                                                      void *host_priv_data)
734 {
735     struct v3_guest *guest= (struct v3_guest*)host_priv_data;
736     struct palacios_host_device_user *dev;
737     struct palacios_host_dev * host_dev = NULL;
738     unsigned long f;
739
740     /*
741       I will create the device in the list and then wait
742       for the user side to attach
743     */
744
745     if (guest == NULL) {
746         return 0;
747     }
748     
749
750     host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
751
752     if (host_dev == NULL) {
753         ERROR("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
754         return 0;
755     }
756
757
758     if (strncasecmp(url,"user:",5)) { 
759         ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
760         return NULL;
761     }
762
763     // Check to see if a device of this url already exists, which would be ugly
764     palacios_spinlock_lock_irqsave(&(host_dev->lock),f);
765     list_for_each_entry(dev,&(host_dev->devs), node) {
766         if (!strncasecmp(url,dev->url,MAX_URL)) { 
767             // found it
768             palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
769             ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
770             return NULL;
771         }
772     }
773     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
774
775
776     INFO("palacios: creating host device \"%s\"\n",url);
777
778     dev = palacios_alloc(sizeof(struct palacios_host_device_user));
779     
780     if (!dev) { 
781         ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
782         return NULL;
783     }
784
785     memset(dev,0,sizeof(struct palacios_host_device_user));
786     
787     strncpy(dev->url,url,MAX_URL);
788     
789     dev->guestdev = gdev;
790     
791     dev->guestintr = gintr;
792     
793     dev->guest = guest;
794
795     palacios_spinlock_init(&(dev->lock));
796
797     init_waitqueue_head(&(dev->user_wait_queue));
798     init_waitqueue_head(&(dev->host_wait_queue));
799
800     // Insert ourselves into the list
801     palacios_spinlock_lock_irqsave(&(host_dev->lock),f);
802     list_add(&(dev->node),&(host_dev->devs));
803     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
804
805     INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
806
807     return dev;
808
809 }
810
811
812
813 static int palacios_host_dev_close(v3_host_dev_t hostdev)
814 {
815     unsigned long f1, f2;
816
817     struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
818     struct palacios_host_dev * host_dev = NULL;
819
820     INFO("palacios: closing host device \"%s\"\n",dev->url);
821
822     if ((dev == NULL) || (dev->guest == NULL)) {
823         return -1;
824     }
825
826     host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
827
828     
829     if (host_dev == NULL) {
830         return -1;
831     }
832
833     palacios_spinlock_lock_irqsave(&(host_dev->lock),f1);
834
835     palacios_spinlock_lock_irqsave(&(dev->lock),f2);
836
837     if (dev->connected) { 
838         dev->connected=0;
839         // After this, any user side request will return -EFAULT
840     }
841
842     list_del(&(dev->node));
843     
844     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
845     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
846     
847     palacios_spinlock_deinit(&(dev->lock));
848
849     palacios_host_dev_user_free(dev);
850
851     return 0;
852 }
853
854
855
856         
857 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
858                                           uint16_t      port,
859                                           void          *dest,
860                                           uint64_t      len)
861 {
862     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
863     unsigned long f;
864     uint64_t op_len;
865
866     DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
867             
868     if (palacios_host_dev_rendezvous(dev)) {
869         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
870         return 0;
871     }
872     palacios_spinlock_lock_irqsave(&(dev->lock),f);
873
874     if (dev->waiting) { 
875         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
876         ERROR("palacios: guest issued i/o read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
877         return 0;
878     }
879
880     // if we're not waiting on user, we have access to
881     // to the request and response fields
882     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
883     
884     // resize request (no data)
885     if (!palacios_bigenough_reqresp(dev->req,0)) {
886         // not enough room.
887         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
888         
889         if (palacios_resize_reqresp(&(dev->req),0,0)) {
890             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
891             return 0;
892         } 
893     }
894     
895
896     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
897     dev->req->port=port;
898     dev->req->op_len=len;
899     dev->req->gpa=0;
900     dev->req->conf_addr=0;
901     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
902
903     dev->waiting=1;
904     
905     // hand over to the user space and wait for it to respond
906     cycle_request_response(dev);
907
908     // We're back!   So now we'll hand the response back to Palacios
909     // no need to lock, we own the response since 
910     // waiting is now 0
911
912     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
913
914     memcpy(dest,dev->resp->data, op_len);
915     
916     return op_len;
917 }
918
919 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
920                                            void *        gpa,
921                                            void          *dest,
922                                            uint64_t      len)
923 {
924     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
925     unsigned long f;
926     uint64_t op_len;
927
928     DEEP_DEBUG_PRINT("palacios: hostdev: read mem  0x%p\n",gpa);
929
930     
931     if (palacios_host_dev_rendezvous(dev)) {
932         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
933         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
934         return 0;
935     }
936     palacios_spinlock_lock_irqsave(&(dev->lock),f);
937
938     if (dev->waiting) { 
939         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
940         ERROR("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
941         return 0;
942     }
943
944     // We now are assured to have ownership over request
945     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
946     
947     // resize request (no data)
948     if (!palacios_bigenough_reqresp(dev->req,0)) {
949         // not enough room.
950         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
951         
952         if (palacios_resize_reqresp(&(dev->req),0,0)) {
953             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
954             return 0;
955         }
956     }
957
958     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
959     dev->req->port=0;
960     dev->req->op_len=len;
961     dev->req->gpa=gpa;
962     dev->req->conf_addr=0;
963     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
964
965     dev->waiting=1;
966     
967     // hand over to the user space and wait for it to respond
968     cycle_request_response(dev);
969
970     // We're back!   So now we'll hand the response back to Palacios
971
972     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
973
974     memcpy(dest,dev->resp->data, op_len);
975     
976     return op_len;
977 }
978
979 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
980                                             uint64_t      offset,
981                                             void          *dest,
982                                             uint64_t      len)
983 {
984     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
985     unsigned long f;
986     uint64_t op_len;
987
988     DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p (len=%lld)\n",(void*)offset, len);
989
990     
991     if (palacios_host_dev_rendezvous(dev)) {
992         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
993         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
994         return 0;
995     }
996     palacios_spinlock_lock_irqsave(&(dev->lock),f);
997
998     if (dev->waiting) { 
999         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1000         ERROR("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
1001         return 0;
1002     }
1003     
1004     // Now have exclusive access to request
1005     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1006
1007     // resize request (no data)
1008     if (!palacios_bigenough_reqresp(dev->req,0)) {
1009         // not enough room.
1010         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1011         
1012         if (palacios_resize_reqresp(&(dev->req),0,0)) {
1013             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1014             return 0;
1015         } 
1016     }
1017
1018     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1019     dev->req->port=0;
1020     dev->req->op_len=len;
1021     dev->req->gpa=0;
1022     dev->req->conf_addr=offset;
1023     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1024
1025     dev->waiting=1;
1026     
1027     // hand over to the user space and wait for it to respond
1028     cycle_request_response(dev);
1029
1030     // We're back!   So now we'll hand the response back to Palacios
1031
1032     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1033
1034     memcpy(dest,dev->resp->data, op_len);
1035     
1036     return op_len;
1037 }
1038
1039
1040 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1041                                            uint16_t      port,
1042                                            void          *src,
1043                                            uint64_t      len)
1044 {
1045     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1046     unsigned long f;
1047     uint64_t op_len;
1048
1049     DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1050
1051     
1052     if (palacios_host_dev_rendezvous(dev)) {
1053         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1054         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1055         return 0;
1056     }
1057     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1058
1059     if (dev->waiting) { 
1060         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1061         ERROR("palacios: guest issued i/o write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
1062         return 0;
1063     }
1064
1065     // have exclusive access to request
1066     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1067         
1068     // resize request 
1069     if (!palacios_bigenough_reqresp(dev->req,len)) {
1070         // not enough room.
1071         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1072         
1073         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1074             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1075             return 0;
1076         } 
1077     }
1078
1079     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1080     dev->req->port=port;
1081     dev->req->op_len=len;
1082     dev->req->gpa=0;
1083     dev->req->conf_addr=0;
1084     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1085
1086     memcpy(dev->req->data,src,len);
1087
1088     dev->waiting=1;
1089
1090     // hand over to the user space and wait for it to respond
1091     cycle_request_response(dev);
1092
1093     // We're back!   So now we'll hand the response back to Palacios
1094
1095     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1096
1097     return op_len;
1098 }
1099
1100
1101 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1102                                             void *        gpa,
1103                                             void          *src,
1104                                             uint64_t      len)
1105 {
1106     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1107     unsigned long f;
1108     uint64_t op_len;
1109
1110     DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1111
1112     
1113     if (palacios_host_dev_rendezvous(dev)) {
1114         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1115         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1116         return 0;
1117     }
1118
1119     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1120
1121     if (dev->waiting) { 
1122         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1123         ERROR("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
1124         return 0;
1125     }
1126     
1127     // Now have exclusive access to request
1128     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1129     
1130     // resize request 
1131     if (!palacios_bigenough_reqresp(dev->req,len)) {
1132         // not enough room.
1133         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1134         
1135         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1136             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1137             return 0;
1138         } 
1139     }
1140
1141     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1142     dev->req->port=0;
1143     dev->req->op_len=len;
1144     dev->req->gpa=gpa;
1145     dev->req->conf_addr=0;
1146     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1147
1148     memcpy(dev->req->data,src,len);
1149
1150     dev->waiting=1;
1151     
1152     // hand over to the user space and wait for it to respond
1153     cycle_request_response(dev);
1154
1155     // We're back!   So now we'll hand the response back to Palacios
1156
1157     op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1158
1159     return op_len;
1160 }
1161
1162
1163
1164
1165 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1166                                              uint64_t      offset,
1167                                              void          *src,
1168                                              uint64_t      len)
1169 {
1170     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1171     unsigned long f;
1172     uint64_t op_len;
1173
1174     DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1175
1176     
1177     if (palacios_host_dev_rendezvous(dev)) {
1178         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1179         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1180         return 0;
1181     }
1182     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1183
1184     if (dev->waiting) { 
1185         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1186         ERROR("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
1187         return 0;
1188     }
1189     
1190     // Have exclusive access to request
1191     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1192
1193     // resize request 
1194     if (!palacios_bigenough_reqresp(dev->req,len)) {
1195         // not enough room.
1196         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1197         
1198         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1199             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1200             return 0;
1201         } 
1202     }
1203
1204     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1205     dev->req->port=0;
1206     dev->req->op_len=len;
1207     dev->req->gpa=0;
1208     dev->req->conf_addr=offset;
1209     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1210
1211     memcpy(dev->req->data,src,len);
1212
1213     dev->waiting=1;
1214
1215     // hand over to the user space and wait for it to respond
1216     cycle_request_response(dev);
1217
1218     // We're back!   So now we'll hand the response back to Palacios
1219
1220     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1221
1222     return op_len;
1223 }
1224  
1225  
1226 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1227 {
1228     // we don't care
1229     return 0;
1230 }
1231  
1232
1233
1234
1235
1236 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1237     .open                       = palacios_host_dev_open_deferred,
1238     .close                      = palacios_host_dev_close,
1239     .read_io                    = palacios_host_dev_read_io,
1240     .write_io                   = palacios_host_dev_write_io,
1241     .read_mem                   = palacios_host_dev_read_mem,
1242     .write_mem                  = palacios_host_dev_write_mem,
1243     .read_config                = palacios_host_dev_read_conf,
1244     .write_config               = palacios_host_dev_write_conf,
1245     .ack_irq                    = palacios_host_dev_ack_irq,
1246 };
1247
1248
1249
1250 static int host_dev_init( void ) {
1251     V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1252     
1253     return 0;
1254 }
1255
1256
1257 static int host_dev_deinit(void) { 
1258     // nothing to do
1259     return 0;
1260 }
1261
1262 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1263     struct palacios_host_dev * host_dev = palacios_alloc(sizeof(struct palacios_host_dev));
1264
1265     if (!host_dev) { 
1266         ERROR("palacios: failed to do guest_init for host device\n");
1267         return -1;
1268     }
1269     
1270     
1271     INIT_LIST_HEAD(&(host_dev->devs));
1272     palacios_spinlock_init(&(host_dev->lock));
1273
1274     *vm_data = host_dev;
1275
1276
1277     add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
1278
1279     return 0;
1280 }
1281
1282
1283 static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) {
1284
1285     struct palacios_host_dev * host_dev = (struct palacios_host_dev *) vm_data;
1286     remove_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT);
1287     palacios_spinlock_deinit(&(host_dev->lock));
1288     palacios_free(host_dev);
1289     return 0;
1290 }
1291
1292
1293
1294
1295 static struct linux_ext host_dev_ext = {
1296     .name = "HOST_DEVICE_INTERFACE",
1297     .init = host_dev_init,
1298     .deinit = host_dev_deinit,
1299     .guest_init = host_dev_guest_init,
1300     .guest_deinit = host_dev_guest_deinit
1301 };
1302
1303
1304 register_extension(&host_dev_ext);