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 and sanity-checking of integer overflow, null comparisons, dead code (Coverit...
[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                     // possible overflow here, but only if user is asking for too much...
373                     void *temp = palacios_alloc(op.len);
374
375                     DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
376
377                     if (!temp) { 
378                         ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
379                         return -EFAULT;
380                     }
381                     
382                     if (v3_host_dev_read_guest_mem(dev,
383                                                    dev->guestdev,
384                                                    op.gpa,
385                                                    temp,
386                                                    op.len) != op.len) {
387                         ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
388                         palacios_free(temp);
389                         return -EFAULT;
390                     }
391                     
392                     if (copy_to_user(op.data,temp,op.len)) { 
393                         ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
394                         palacios_free(temp);
395                         return -EFAULT;
396                     }
397
398                     palacios_free(temp);
399
400                     return op.len;
401                 }
402                     break;
403                     
404
405                 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
406                     void *temp;
407                     
408                     DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
409
410                     temp = palacios_alloc(op.len);
411
412                     if (!temp) { 
413                         ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
414                         return -EFAULT;
415                     }
416                     
417                     if (copy_from_user(temp,op.data,op.len)) { 
418                         ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
419                         palacios_free(temp);
420                         return -EFAULT;
421                     }
422                     
423                     if (v3_host_dev_write_guest_mem(dev,
424                                                     dev->guestdev,
425                                                     op.gpa,
426                                                     temp,
427                                                     op.len) != op.len) {
428                         ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
429                         palacios_free(temp);
430                         return -EFAULT;
431                     }
432
433                     palacios_free(temp);
434                     
435                     return op.len;
436                 }
437                     break;
438
439                 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_RAISE_GUEST: {
440
441                     DEEP_DEBUG_PRINT("palacios: hostdev: irq raise guest\n");
442
443                     return  v3_host_dev_raise_irq(dev, dev->guestdev, dev->guestintr, op.irq);
444                 }
445                     break;
446                 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_LOWER_GUEST: {
447
448                     DEEP_DEBUG_PRINT("palacios: hostdev: irq lower guest\n");
449
450                     return  v3_host_dev_lower_irq(dev, dev->guestdev, dev->guestintr, op.irq);
451                 }
452                     break;
453
454                 default:
455                     ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
456                     return -EFAULT;
457                     break;
458             }
459         }
460             break;
461
462         case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
463             
464             unsigned long f;
465
466
467             DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
468             
469             palacios_spinlock_lock_irqsave(&(dev->lock),f);
470             
471             if (!(dev->waiting)) { 
472                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
473                 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
474                 schedule();  // avoid livelock for polling user space process  SUSPICOUS
475                 return 0; // no request available now
476             } 
477
478             // safe to unlock here since if we are in the waiting state
479             // the palacios side will not modify the request
480             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
481
482             if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) { 
483                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
484                 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
485                 return -EFAULT; // failed to copy!
486
487             }
488             
489             DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
490
491             return 1; // have request for you
492             
493         }
494             
495             break;
496             
497         case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
498             
499             unsigned long f;
500             
501             palacios_spinlock_lock_irqsave(&(dev->lock),f);
502             
503             DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
504
505             if (!(dev->waiting) || !(dev->req)) { 
506                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
507                 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
508                 return 0; // no request available now
509             } 
510
511             // Safe to unlock here since if we are in the waiting 
512             // state, the request will not be modified by the palacios side
513             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
514             
515             if (copy_to_user(argp,dev->req,dev->req->data_len)) { 
516                 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
517                 return -EFAULT; // failed to copy!
518             }
519     
520             DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
521             
522             return 1; // copied request for you
523         }
524             break;
525             
526         case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
527
528             unsigned long f;
529             uint64_t user_datalen;
530             uint64_t old_len;
531             
532             palacios_spinlock_lock_irqsave(&(dev->lock),f);
533             
534             DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
535
536             if (!(dev->waiting)) { 
537                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
538                 ERROR("palacios: hostdev: no matching request for pushed response\n");
539                 return 0; // no request outstanding, so we do not need a response!
540             }
541             
542             // Safe to unlock here as the palacios side will not
543             // modify the request or copy the response until we
544             // reset dev->waiting
545             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
546
547             if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) { 
548                 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
549                 return -EFAULT; // failed to copy!
550             } 
551
552             if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) { 
553                 // bad user
554                 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
555                 return -EFAULT;
556             }
557
558             if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
559                 // not enough room.
560                 DEEP_DEBUG_PRINT("palacios: response not big enough, resizing on device \"%s\"\n",dev->url);
561
562                 
563                 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
564                     ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
565                     return -EFAULT;
566                 } 
567             }
568
569             //We only copy data_len bytes from user, but we will
570             //overwrite the len field, so we preserve and then restore
571             old_len = dev->resp->len;
572             if (copy_from_user(dev->resp, argp, user_datalen)) { 
573                 dev->resp->len=old_len;
574                 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
575                 return -EFAULT; // failed to copy!
576             } 
577             dev->resp->len=old_len;
578             
579             DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
580             // now have valid response!
581             dev->waiting=0;
582
583             // wake the palacios side up so that it sees it
584             cycle_response_request(dev);
585
586             return 1; // done
587         }
588             break;
589             
590         default:
591             ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
592             return -EFAULT;
593             break;
594     }
595     
596 }
597
598 static struct file_operations host_dev_fops = {
599     .poll     = host_dev_poll,
600     .release  = host_dev_release,
601     .compat_ioctl = host_dev_ioctl,
602     .unlocked_ioctl = host_dev_ioctl,
603 };
604
605
606
607 static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) 
608 {
609     void __user * argp = (void __user *)arg;
610     char url[MAX_URL];
611     struct palacios_host_dev * host_dev = priv_data;
612     struct palacios_host_device_user *dev;
613     unsigned long f1, f2;
614     int i;
615
616
617
618     if (copy_from_user(url, argp, MAX_URL)) {
619         ERROR("copy from user error getting url for host device connect...\n");
620         return -EFAULT;
621     }
622
623     // currently only support user: types:
624     if (strncasecmp(url,"user:",5)) { 
625         ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
626         return -1;
627     }
628     
629     INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
630     
631     // We will scan the list looking for the relevant
632     // URL.  If we don't find it after a while, we give up
633     
634     for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
635         palacios_spinlock_lock_irqsave(&(host_dev->lock),f1);
636         list_for_each_entry(dev,&(host_dev->devs), node) {
637             if (!strncasecmp(url,dev->url,MAX_URL)) { 
638                 // found it
639                 palacios_spinlock_lock_irqsave(&(dev->lock),f2);
640                 if (dev->connected) { 
641                     ERROR("palacios: device for \"%s\" is already connected!\n",url);
642                     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
643                     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
644                     return -1;
645                 } else {
646                     dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
647                     if (dev->fd<0) { 
648                         ERROR("palacios: cannot create fd for device \"%s\"\n",url);
649                         palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
650                         palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
651                         return -1;
652                     }
653                     dev->connected=1;
654                     dev->waiting=0;
655                     if (dev->req) { 
656                         palacios_free(dev->req);
657                         dev->req=0;
658                     } 
659                     if (dev->resp) { 
660                         palacios_free(dev->resp);
661                         dev->resp=0;
662                     }
663                     INFO("palacios: connected fd for device \"%s\"\n",url);
664                     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
665                     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
666                     return dev->fd;
667                 }
668                 palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
669             }
670         }
671         palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
672         
673         ssleep(RENDEZVOUS_RETRY_SECS);
674     }
675     
676     ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
677     
678     return -1;
679     
680 }
681
682
683
684
685
686
687
688
689 /***************************************************************************************
690
691    Following this is the implementation of the palacios->host interface
692
693 **************************************************************************************/
694
695
696 /* Attempt to rendezvous with the user device if no device is currently connected */
697 static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
698 {
699     unsigned long f;
700     int i;
701
702     if (dev->connected) { 
703         return 0;
704     }
705
706    
707     INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
708
709     // Now wait until we are noticed!
710     for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
711         palacios_spinlock_lock_irqsave(&(dev->lock),f);
712         if (dev->connected) { 
713             INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
714             palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
715             return 0;
716         }
717         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
718         ssleep(RENDEZVOUS_RETRY_SECS);
719     }
720     
721     ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
722
723     // We stay in the list because a future rendezvous might happen
724     
725     return -1;
726 }
727
728
729 /* Creates the device without rendezvous */
730 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
731                                                      v3_bus_class_t bus,
732                                                      v3_guest_dev_t gdev,
733                                                      v3_guest_dev_intr_t gintr,
734                                                      void *host_priv_data)
735 {
736     struct v3_guest *guest= (struct v3_guest*)host_priv_data;
737     struct palacios_host_device_user *dev;
738     struct palacios_host_dev * host_dev = NULL;
739     unsigned long f;
740
741     /*
742       I will create the device in the list and then wait
743       for the user side to attach
744     */
745
746     if (guest == NULL) {
747         return 0;
748     }
749     
750
751     host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
752
753     if (host_dev == NULL) {
754         ERROR("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
755         return 0;
756     }
757
758
759     if (strncasecmp(url,"user:",5)) { 
760         ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
761         return NULL;
762     }
763
764     // Check to see if a device of this url already exists, which would be ugly
765     palacios_spinlock_lock_irqsave(&(host_dev->lock),f);
766     list_for_each_entry(dev,&(host_dev->devs), node) {
767         if (!strncasecmp(url,dev->url,MAX_URL)) { 
768             // found it
769             palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
770             ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
771             return NULL;
772         }
773     }
774     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
775
776
777     INFO("palacios: creating host device \"%s\"\n",url);
778
779     dev = palacios_alloc(sizeof(struct palacios_host_device_user));
780     
781     if (!dev) { 
782         ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
783         return NULL;
784     }
785
786     memset(dev,0,sizeof(struct palacios_host_device_user));
787     
788     strncpy(dev->url,url,MAX_URL);
789     dev->url[MAX_URL-1] = 0;
790     
791     dev->guestdev = gdev;
792     
793     dev->guestintr = gintr;
794     
795     dev->guest = guest;
796
797     palacios_spinlock_init(&(dev->lock));
798
799     init_waitqueue_head(&(dev->user_wait_queue));
800     init_waitqueue_head(&(dev->host_wait_queue));
801
802     // Insert ourselves into the list
803     palacios_spinlock_lock_irqsave(&(host_dev->lock),f);
804     list_add(&(dev->node),&(host_dev->devs));
805     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f);
806
807     INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
808
809     return dev;
810
811 }
812
813
814
815 static int palacios_host_dev_close(v3_host_dev_t hostdev)
816 {
817     unsigned long f1, f2;
818
819     struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
820     struct palacios_host_dev * host_dev = NULL;
821
822     INFO("palacios: closing host device \"%s\"\n",dev->url);
823
824     if ((dev == NULL) || (dev->guest == NULL)) {
825         return -1;
826     }
827
828     host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
829
830     
831     if (host_dev == NULL) {
832         return -1;
833     }
834
835     palacios_spinlock_lock_irqsave(&(host_dev->lock),f1);
836
837     palacios_spinlock_lock_irqsave(&(dev->lock),f2);
838
839     if (dev->connected) { 
840         dev->connected=0;
841         // After this, any user side request will return -EFAULT
842     }
843
844     list_del(&(dev->node));
845     
846     palacios_spinlock_unlock_irqrestore(&(dev->lock),f2);
847     palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1);
848     
849     palacios_spinlock_deinit(&(dev->lock));
850
851     palacios_host_dev_user_free(dev);
852
853     return 0;
854 }
855
856
857
858         
859 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
860                                           uint16_t      port,
861                                           void          *dest,
862                                           uint64_t      len)
863 {
864     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
865     unsigned long f;
866     uint64_t op_len;
867
868     DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
869             
870     if (palacios_host_dev_rendezvous(dev)) {
871         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
872         return 0;
873     }
874     palacios_spinlock_lock_irqsave(&(dev->lock),f);
875
876     if (dev->waiting) { 
877         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
878         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);
879         return 0;
880     }
881
882     // if we're not waiting on user, we have access to
883     // to the request and response fields
884     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
885     
886     // resize request (no data)
887     if (!palacios_bigenough_reqresp(dev->req,0)) {
888         // not enough room.
889         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
890         
891         if (palacios_resize_reqresp(&(dev->req),0,0)) {
892             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
893             return 0;
894         } 
895     }
896     
897
898     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
899     dev->req->port=port;
900     dev->req->op_len=len;
901     dev->req->gpa=0;
902     dev->req->conf_addr=0;
903     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
904
905     dev->waiting=1;
906     
907     // hand over to the user space and wait for it to respond
908     cycle_request_response(dev);
909
910     // We're back!   So now we'll hand the response back to Palacios
911     // no need to lock, we own the response since 
912     // waiting is now 0
913
914     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
915
916     memcpy(dest,dev->resp->data, op_len);
917     
918     return op_len;
919 }
920
921 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
922                                            void *        gpa,
923                                            void          *dest,
924                                            uint64_t      len)
925 {
926     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
927     unsigned long f;
928     uint64_t op_len;
929
930     DEEP_DEBUG_PRINT("palacios: hostdev: read mem  0x%p\n",gpa);
931
932     
933     if (palacios_host_dev_rendezvous(dev)) {
934         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
935         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
936         return 0;
937     }
938     palacios_spinlock_lock_irqsave(&(dev->lock),f);
939
940     if (dev->waiting) { 
941         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
942         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);
943         return 0;
944     }
945
946     // We now are assured to have ownership over request
947     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
948     
949     // resize request (no data)
950     if (!palacios_bigenough_reqresp(dev->req,0)) {
951         // not enough room.
952         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
953         
954         if (palacios_resize_reqresp(&(dev->req),0,0)) {
955             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
956             return 0;
957         }
958     }
959
960     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
961     dev->req->port=0;
962     dev->req->op_len=len;
963     dev->req->gpa=gpa;
964     dev->req->conf_addr=0;
965     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
966
967     dev->waiting=1;
968     
969     // hand over to the user space and wait for it to respond
970     cycle_request_response(dev);
971
972     // We're back!   So now we'll hand the response back to Palacios
973
974     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
975
976     memcpy(dest,dev->resp->data, op_len);
977     
978     return op_len;
979 }
980
981 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
982                                             uint64_t      offset,
983                                             void          *dest,
984                                             uint64_t      len)
985 {
986     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
987     unsigned long f;
988     uint64_t op_len;
989
990     DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p (len=%lld)\n",(void*)offset, len);
991
992     
993     if (palacios_host_dev_rendezvous(dev)) {
994         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
995         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
996         return 0;
997     }
998     palacios_spinlock_lock_irqsave(&(dev->lock),f);
999
1000     if (dev->waiting) { 
1001         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1002         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);
1003         return 0;
1004     }
1005     
1006     // Now have exclusive access to request
1007     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1008
1009     // resize request (no data)
1010     if (!palacios_bigenough_reqresp(dev->req,0)) {
1011         // not enough room.
1012         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1013         
1014         if (palacios_resize_reqresp(&(dev->req),0,0)) {
1015             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1016             return 0;
1017         } 
1018     }
1019
1020     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1021     dev->req->port=0;
1022     dev->req->op_len=len;
1023     dev->req->gpa=0;
1024     dev->req->conf_addr=offset;
1025     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1026
1027     dev->waiting=1;
1028     
1029     // hand over to the user space and wait for it to respond
1030     cycle_request_response(dev);
1031
1032     // We're back!   So now we'll hand the response back to Palacios
1033
1034     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1035
1036     memcpy(dest,dev->resp->data, op_len);
1037     
1038     return op_len;
1039 }
1040
1041
1042 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1043                                            uint16_t      port,
1044                                            void          *src,
1045                                            uint64_t      len)
1046 {
1047     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1048     unsigned long f;
1049     uint64_t op_len;
1050
1051     DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1052
1053     
1054     if (palacios_host_dev_rendezvous(dev)) {
1055         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1056         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1057         return 0;
1058     }
1059     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1060
1061     if (dev->waiting) { 
1062         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1063         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);
1064         return 0;
1065     }
1066
1067     // have exclusive access to request
1068     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1069         
1070     // resize request 
1071     if (!palacios_bigenough_reqresp(dev->req,len)) {
1072         // not enough room.
1073         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1074         
1075         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1076             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1077             return 0;
1078         } 
1079     }
1080
1081     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1082     dev->req->port=port;
1083     dev->req->op_len=len;
1084     dev->req->gpa=0;
1085     dev->req->conf_addr=0;
1086     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1087
1088     memcpy(dev->req->data,src,len);
1089
1090     dev->waiting=1;
1091
1092     // hand over to the user space and wait for it to respond
1093     cycle_request_response(dev);
1094
1095     // We're back!   So now we'll hand the response back to Palacios
1096
1097     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1098
1099     return op_len;
1100 }
1101
1102
1103 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1104                                             void *        gpa,
1105                                             void          *src,
1106                                             uint64_t      len)
1107 {
1108     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1109     unsigned long f;
1110     uint64_t op_len;
1111
1112     DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1113
1114     
1115     if (palacios_host_dev_rendezvous(dev)) {
1116         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1117         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1118         return 0;
1119     }
1120
1121     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1122
1123     if (dev->waiting) { 
1124         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1125         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);
1126         return 0;
1127     }
1128     
1129     // Now have exclusive access to request
1130     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1131     
1132     // resize request 
1133     if (!palacios_bigenough_reqresp(dev->req,len)) {
1134         // not enough room.
1135         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1136         
1137         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1138             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1139             return 0;
1140         } 
1141     }
1142
1143     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1144     dev->req->port=0;
1145     dev->req->op_len=len;
1146     dev->req->gpa=gpa;
1147     dev->req->conf_addr=0;
1148     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1149
1150     memcpy(dev->req->data,src,len);
1151
1152     dev->waiting=1;
1153     
1154     // hand over to the user space and wait for it to respond
1155     cycle_request_response(dev);
1156
1157     // We're back!   So now we'll hand the response back to Palacios
1158
1159     op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1160
1161     return op_len;
1162 }
1163
1164
1165
1166
1167 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1168                                              uint64_t      offset,
1169                                              void          *src,
1170                                              uint64_t      len)
1171 {
1172     struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1173     unsigned long f;
1174     uint64_t op_len;
1175
1176     DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1177
1178     
1179     if (palacios_host_dev_rendezvous(dev)) {
1180         //palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1181         ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1182         return 0;
1183     }
1184     palacios_spinlock_lock_irqsave(&(dev->lock),f);
1185
1186     if (dev->waiting) { 
1187         palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1188         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);
1189         return 0;
1190     }
1191     
1192     // Have exclusive access to request
1193     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
1194
1195     // resize request 
1196     if (!palacios_bigenough_reqresp(dev->req,len)) {
1197         // not enough room.
1198         DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
1199         
1200         if (palacios_resize_reqresp(&(dev->req),len,0)) {
1201             ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1202             return 0;
1203         } 
1204     }
1205
1206     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1207     dev->req->port=0;
1208     dev->req->op_len=len;
1209     dev->req->gpa=0;
1210     dev->req->conf_addr=offset;
1211     dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1212
1213     memcpy(dev->req->data,src,len);
1214
1215     dev->waiting=1;
1216
1217     // hand over to the user space and wait for it to respond
1218     cycle_request_response(dev);
1219
1220     // We're back!   So now we'll hand the response back to Palacios
1221
1222     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1223
1224     return op_len;
1225 }
1226  
1227  
1228 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1229 {
1230     // we don't care
1231     return 0;
1232 }
1233  
1234
1235
1236
1237
1238 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1239     .open                       = palacios_host_dev_open_deferred,
1240     .close                      = palacios_host_dev_close,
1241     .read_io                    = palacios_host_dev_read_io,
1242     .write_io                   = palacios_host_dev_write_io,
1243     .read_mem                   = palacios_host_dev_read_mem,
1244     .write_mem                  = palacios_host_dev_write_mem,
1245     .read_config                = palacios_host_dev_read_conf,
1246     .write_config               = palacios_host_dev_write_conf,
1247     .ack_irq                    = palacios_host_dev_ack_irq,
1248 };
1249
1250
1251
1252 static int host_dev_init( void ) {
1253     V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1254     
1255     return 0;
1256 }
1257
1258
1259 static int host_dev_deinit(void) { 
1260     // nothing to do
1261     return 0;
1262 }
1263
1264 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1265     struct palacios_host_dev * host_dev = palacios_alloc(sizeof(struct palacios_host_dev));
1266
1267     if (!host_dev) { 
1268         ERROR("palacios: failed to do guest_init for host device\n");
1269         return -1;
1270     }
1271     
1272     
1273     INIT_LIST_HEAD(&(host_dev->devs));
1274     palacios_spinlock_init(&(host_dev->lock));
1275
1276     *vm_data = host_dev;
1277
1278
1279     add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
1280
1281     return 0;
1282 }
1283
1284
1285 static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) {
1286
1287     struct palacios_host_dev * host_dev = (struct palacios_host_dev *) vm_data;
1288     remove_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT);
1289     palacios_spinlock_deinit(&(host_dev->lock));
1290     palacios_free(host_dev);
1291     return 0;
1292 }
1293
1294
1295
1296
1297 static struct linux_ext host_dev_ext = {
1298     .name = "HOST_DEVICE_INTERFACE",
1299     .init = host_dev_init,
1300     .deinit = host_dev_deinit,
1301     .guest_init = host_dev_guest_init,
1302     .guest_deinit = host_dev_guest_deinit
1303 };
1304
1305
1306 register_extension(&host_dev_ext);