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.


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