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.


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