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.


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