2 * Host device interface + user-space device interface
6 #include <linux/device.h>
7 #include <linux/cdev.h>
8 #include <linux/errno.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>
17 #include <interfaces/vmm_host_dev.h>
20 #include "palacios-host-dev.h"
21 #include "palacios-host-dev-user.h"
26 There are two things in this file:
29 1. An implementation of the Palacios host device interface that will
30 accept any URL from Palacios. Currently, the only URL type it will
31 handle is user:<name>, but it should be clear how to extend with
34 Palacios opens a host device by issuing something like this:
36 palacios_host_dev_open( impl="user:foo" busclass=pci, opaque )
38 This will attempt to rendezvous with the user space device The
39 rendevzous retry and timeout periods can be set below.
41 2. An implementation of user: urls - the host interface is mapped
42 into an RPC-like interface to/from user space via a file
45 The user space gets a file descriptor like this:
47 int vmfd = open("/dev/v3-vmX",...);
49 int devfd = ioctl(vmfd,V3_HOST_DEV_CONNECT,"user:foo");
51 This will attempt to rendezvous with the host side.
53 If it returns successfully, you can now issue synchronous,
54 blocking RPCs to the guest to read/write its memory and inject
55 irqs. This means that a user->host request is handled
56 immediately, and independently of any host->user request.
58 struct palacios_host_dev_user_op op;
61 op.type = PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST;
64 ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL, &op);
66 // return value is # bytes read or written; or 0 if irq injected
67 // negative value is error
69 The interface from the host to the user side is asynchronous
70 blocking RPC. Any host device will have at most one outstanding
71 request from palacios. The implementation here stores the
72 request until the user side is ready to accept it. The user side
73 can check if there is a request via a poll/select or an ioctl.
74 The ioctl also returns the needed size for the request structure.
75 After the user side has a request, it is expected to process it,
76 perhaps making user->host requests as described above, and then
77 return a response. Only one host->user request should be in
78 progress at any time in the user space.
80 What this looks like is:
82 poll(...devfd for read...) or select(...devfd for read...)
84 if (devfd is marked readable) {
87 ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&size);
88 // returns 1 if there is a request, 0 if not, negative on err
90 struct palacios_host_dev_host_request_response *req;
92 req = allocate req to be at least size bytes long
94 ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL,req)
95 // returns 1 if there is a request, 0 if not, negative on err
97 // process request, perhaps using above user->host request
98 // build response structure
99 // resp.data_len == size of structure including relevant data at end
101 ioctl(devfd,V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL,resp);
102 // returns 0 if there is no outstanding request (user error)
103 // 1 on success, negative on error
112 #define RENDEZVOUS_WAIT_SECS 60
113 #define RENDEZVOUS_RETRY_SECS 1
116 struct palacios_host_device_user {
118 int connected; // is the user space connected to this?
119 int waiting; // am I waiting for a user-space response?
121 int fd; // what is the user space fd?
123 char url[MAX_URL]; // what is the url describing the device
125 v3_guest_dev_t guestdev; // what is the palacios-side device
127 wait_queue_head_t user_wait_queue; // user space processes waiting on us (should be only one)
128 wait_queue_head_t host_wait_queue; // host threads (should only be one) waiting on user space
130 struct v3_guest *guest; // my guest
131 struct palacios_host_dev_host_request_response *req; // curent request
132 struct palacios_host_dev_host_request_response *resp; // curent response
134 struct list_head node; // for adding me to the list of hostdevs this VM has
138 /**************************************************************************************
140 *************************************************************************************/
142 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
155 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
159 *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
163 (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
167 //let it go if it's big enough
168 uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
170 if (data_size<=cur_len) {
174 struct palacios_host_dev_host_request_response *new;
180 new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
184 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
186 memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
187 new->data_len=(*r)->data_len;
197 static void cycle_request_response(struct palacios_host_device_user *dev)
199 // wake up user side so that polls fall through
200 wake_up_interruptible(&(dev->user_wait_queue));
201 // put us to sleep until the user side wakes us up
202 wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0));
205 static void cycle_response_request(struct palacios_host_device_user *dev)
208 wake_up_interruptible(&(dev->host_wait_queue));
212 /*********************************************************************************************
214 Interface to user space
216 *********************************************************************************************/
220 static unsigned int host_dev_poll(struct file * filp,
221 struct poll_table_struct * poll_tb)
224 struct palacios_host_device_user * dev = filp->private_data;
227 if (!dev->connected) {
231 spin_lock_irqsave(&(dev->lock),f);
234 // Yes, we have a request if you want it!
235 spin_unlock_irqrestore(&(dev->lock),f);
236 return POLLIN | POLLRDNORM;
239 // No request yet, so we need to wait for one to show up.
241 // register ourselves on the user wait queue
242 poll_wait(filp, &(dev->user_wait_queue), poll_tb);
244 spin_unlock_irqrestore(&(dev->lock),f);
246 // We will get called again when that queue is woken up
252 static int host_dev_release(struct inode * i, struct file * filp)
254 struct palacios_host_device_user *dev = filp->private_data;
257 printk("palacios: user side is closing host device \"%s\"\n",dev->url);
259 spin_lock_irqsave(&(dev->lock), f);
261 spin_unlock_irqrestore(&(dev->lock), f);
263 // it is the palacios->host interface's responsibility to ignore
264 // reads/writes until connected is true
270 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
272 void __user *argp = (void __user *)arg;
274 struct palacios_host_device_user *dev = fp->private_data;
277 if (!dev->connected) {
282 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
284 struct palacios_host_dev_user_op op;
286 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
287 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
292 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
293 void *temp = kmalloc(op.len,GFP_KERNEL);
296 printk("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
300 if (v3_host_dev_read_guest_mem(dev->guestdev,
305 printk("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
310 if (copy_to_user(op.data,temp,op.len)) {
311 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
323 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
325 void *temp = kmalloc(op.len,GFP_KERNEL);
328 printk("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
332 if (copy_from_user(temp,op.data,op.len)) {
333 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
338 if (v3_host_dev_write_guest_mem(dev->guestdev,
343 printk("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
354 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
356 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
361 printk("palacios: unknown user request to host device \"%s\"\n",dev->url);
368 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
372 spin_lock_irqsave(&(dev->lock),f);
374 if (!(dev->waiting)) {
375 spin_unlock_irqrestore(&(dev->lock),f);
376 return 0; // no request available now
379 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
380 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
381 spin_unlock_irqrestore(&(dev->lock),f);
382 return -EFAULT; // failed to copy!
385 spin_unlock_irqrestore(&(dev->lock),f);
387 return 1; // have request for you
393 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
397 spin_lock_irqsave(&(dev->lock),f);
399 if (!(dev->waiting)) {
400 spin_unlock_irqrestore(&(dev->lock),f);
401 return 0; // no request available now
404 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
405 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
406 spin_unlock_irqrestore(&(dev->lock),f);
407 return -EFAULT; // failed to copy!
410 spin_unlock_irqrestore(&(dev->lock),f);
412 return 1; // copied request for you
416 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
419 uint64_t user_datalen;
421 spin_lock_irqsave(&(dev->lock),f);
423 if (!(dev->waiting)) {
424 spin_unlock_irqrestore(&(dev->lock),f);
425 return 0; // no request outstanding, so we do not need a response!
428 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
429 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
430 spin_unlock_irqrestore(&(dev->lock),f);
431 return -EFAULT; // failed to copy!
434 if (palacios_resize_reqresp(&(dev->resp),user_datalen,0)) {
435 printk("palacios: unable to resize to accept request of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
436 spin_unlock_irqrestore(&(dev->lock),f);
440 if (copy_from_user(dev->resp, argp, user_datalen)) {
441 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
442 spin_unlock_irqrestore(&(dev->lock),f);
443 return -EFAULT; // failed to copy!
446 // now have valid response!
449 // wake the palacios side up so that it sees it
450 cycle_response_request(dev);
452 spin_unlock_irqrestore(&(dev->lock),f);
459 printk("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
469 static struct file_operations host_dev_fops = {
470 .poll = host_dev_poll,
471 .release = host_dev_release,
472 .ioctl = host_dev_ioctl,
478 int connect_host_dev(struct v3_guest * guest, char *url)
480 struct palacios_host_device_user *dev;
481 unsigned long f1, f2;
484 // currently only support user: types:
485 if (strncasecmp(url,"user:",5)) {
486 printk("palacios: do not currently support host devices of type in \"%s\"\n",url);
490 printk("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
492 // We will scan the list looking for the relevant
493 // URL. If we don't find it after a while, we give up
495 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
496 spin_lock_irqsave(&(guest->hostdev.lock),f1);
497 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
498 if (!strncasecmp(url,dev->url,MAX_URL)) {
500 spin_lock_irqsave(&(dev->lock),f2);
501 if (dev->connected) {
502 printk("palacios: device for \"%s\" is already connected!\n",url);
503 spin_unlock_irqrestore(&(dev->lock),f2);
504 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
507 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
509 printk("palacios: cannot create fd for device \"%s\"\n",url);
510 spin_unlock_irqrestore(&(dev->lock),f2);
511 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
524 printk("palacios: connected fd for device \"%s\"\n",url);
525 spin_unlock_irqrestore(&(dev->lock),f2);
526 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
529 spin_unlock_irqrestore(&(dev->lock),f2);
532 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
534 ssleep(RENDEZVOUS_RETRY_SECS);
537 printk("palacios: timeout waiting for connection for device \"%s\"",url);
550 /***************************************************************************************
552 Following this is the implementation of the palacios->host interface
554 **************************************************************************************/
556 static v3_host_dev_t palacios_host_dev_open(char *url,
559 void *host_priv_data)
561 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
562 struct palacios_host_device_user *dev;
567 I will create the device in the list and then wait
568 for the user side to attach
572 if (strncasecmp(url,"user:",5)) {
573 printk("palacios: do not currently support devices of type in \"%s\"\n",url);
577 // Check to see if a device of this url already exists, which would be ugly
578 spin_lock_irqsave(&(guest->hostdev.lock),f1);
579 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
580 if (!strncasecmp(url,dev->url,MAX_URL)) {
582 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
583 printk("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
587 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
590 printk("palacios: creating host device \"%s\"\n",url);
592 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
595 printk("palacios: cannot allocate for host device \"%s\"\n",url);
599 memset(dev,0,sizeof(struct palacios_host_device_user));
601 strncpy(dev->url,url,MAX_URL);
607 spin_lock_init(&(dev->lock));
609 init_waitqueue_head(&(dev->user_wait_queue));
610 init_waitqueue_head(&(dev->host_wait_queue));
612 printk("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
614 // Insert ourselves into the list
615 spin_lock_irqsave(&(guest->hostdev.lock),f1);
616 list_add(&(dev->node),&(guest->hostdev.devs));
617 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
620 // Now wait until we are noticed!
621 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
622 spin_lock_irqsave(&(dev->lock),f2);
624 printk("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
625 spin_unlock_irqrestore(&(dev->lock),f2);
628 spin_unlock_irqrestore(&(dev->lock),f2);
629 ssleep(RENDEZVOUS_RETRY_SECS);
632 printk("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
634 // get us out of the list
635 spin_lock_irqsave(&(guest->hostdev.lock),f1);
636 list_del(&(dev->node));
637 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
639 palacios_host_dev_user_free(dev);
644 static int palacios_host_dev_close(v3_host_dev_t hostdev)
646 unsigned long f1, f2;
648 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
650 printk("palacios: closing host device \"%s\"\n",dev->url);
652 spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
654 spin_lock_irqsave(&(dev->lock),f2);
656 if (dev->connected) {
658 // After this, any user side request will return -EFAULT
661 list_del(&(dev->node));
663 spin_unlock_irqrestore(&(dev->lock),f2);
664 spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
666 palacios_host_dev_user_free(dev);
674 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
679 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
683 spin_lock_irqsave(&(dev->lock),f);
686 printk("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);
687 spin_unlock_irqrestore(&(dev->lock),f);
691 if (!dev->connected) {
692 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
693 spin_unlock_irqrestore(&(dev->lock),f);
697 // resize request and response in case they will need it
698 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
700 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
702 dev->req->op_len=len;
704 dev->req->conf_addr=0;
705 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
709 spin_unlock_irqrestore(&(dev->lock),f);
711 // hand over to the user space and wait for it to respond
712 cycle_request_response(dev);
714 // We're back! So now we'll hand the response back to Palacios
716 spin_lock_irqsave(&(dev->lock),f);
718 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
720 memcpy(dest,dev->resp->data, op_len);
722 spin_unlock_irqrestore(&(dev->lock),f);
727 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
732 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
736 spin_lock_irqsave(&(dev->lock),f);
739 printk("palacios: guest issued memory read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
740 spin_unlock_irqrestore(&(dev->lock),f);
743 if (!dev->connected) {
744 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
745 spin_unlock_irqrestore(&(dev->lock),f);
749 // resize request and response in case they will need it
750 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
752 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
754 dev->req->op_len=len;
756 dev->req->conf_addr=0;
757 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
761 spin_unlock_irqrestore(&(dev->lock),f);
763 // hand over to the user space and wait for it to respond
764 cycle_request_response(dev);
766 // We're back! So now we'll hand the response back to Palacios
768 spin_lock_irqsave(&(dev->lock),f);
770 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
772 memcpy(dest,dev->resp->data, op_len);
774 spin_unlock_irqrestore(&(dev->lock),f);
779 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
784 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
788 spin_lock_irqsave(&(dev->lock),f);
791 printk("palacios: guest issued config read request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
792 spin_unlock_irqrestore(&(dev->lock),f);
795 if (!dev->connected) {
796 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
797 spin_unlock_irqrestore(&(dev->lock),f);
801 // resize request and response in case they will need it
802 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
804 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
806 dev->req->op_len=len;
808 dev->req->conf_addr=offset;
809 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
813 spin_unlock_irqrestore(&(dev->lock),f);
815 // hand over to the user space and wait for it to respond
816 cycle_request_response(dev);
818 // We're back! So now we'll hand the response back to Palacios
820 spin_lock_irqsave(&(dev->lock),f);
822 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
824 memcpy(dest,dev->resp->data, op_len);
826 spin_unlock_irqrestore(&(dev->lock),f);
832 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
837 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
841 spin_lock_irqsave(&(dev->lock),f);
844 printk("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);
845 spin_unlock_irqrestore(&(dev->lock),f);
848 if (!dev->connected) {
849 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
850 spin_unlock_irqrestore(&(dev->lock),f);
854 // resize request and response in case they will need it
855 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
857 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
859 dev->req->op_len=len;
861 dev->req->conf_addr=0;
862 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
864 memcpy(dev->req->data,src,len);
868 spin_unlock_irqrestore(&(dev->lock),f);
870 // hand over to the user space and wait for it to respond
871 cycle_request_response(dev);
873 // We're back! So now we'll hand the response back to Palacios
875 spin_lock_irqsave(&(dev->lock),f);
877 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
879 spin_unlock_irqrestore(&(dev->lock),f);
885 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
890 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
894 spin_lock_irqsave(&(dev->lock),f);
897 printk("palacios: guest issued memory write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
898 spin_unlock_irqrestore(&(dev->lock),f);
901 if (!dev->connected) {
902 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
903 spin_unlock_irqrestore(&(dev->lock),f);
907 // resize request and response in case they will need it
908 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
910 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
912 dev->req->op_len=len;
914 dev->req->conf_addr=0;
915 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
917 memcpy(dev->req->data,src,len);
921 spin_unlock_irqrestore(&(dev->lock),f);
923 // hand over to the user space and wait for it to respond
924 cycle_request_response(dev);
926 // We're back! So now we'll hand the response back to Palacios
928 spin_lock_irqsave(&(dev->lock),f);
930 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
932 spin_unlock_irqrestore(&(dev->lock),f);
938 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
946 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
951 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
955 spin_lock_irqsave(&(dev->lock),f);
958 printk("palacios: guest issued config write request with host device \"%s\" in wrong state (waiting=%d, connected=%d)\n",dev->url,dev->waiting,dev->connected);
959 spin_unlock_irqrestore(&(dev->lock),f);
962 if (!dev->connected) {
963 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
964 spin_unlock_irqrestore(&(dev->lock),f);
968 // resize request and response in case they will need it
969 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
971 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
973 dev->req->op_len=len;
975 dev->req->conf_addr=offset;
976 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
978 memcpy(dev->req->data,src,len);
982 spin_unlock_irqrestore(&(dev->lock),f);
984 // hand over to the user space and wait for it to respond
985 cycle_request_response(dev);
987 // We're back! So now we'll hand the response back to Palacios
989 spin_lock_irqsave(&(dev->lock),f);
991 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
993 spin_unlock_irqrestore(&(dev->lock),f);
1003 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1004 .open = palacios_host_dev_open,
1005 .close = palacios_host_dev_close,
1006 .read_io = palacios_host_dev_read_io,
1007 .write_io = palacios_host_dev_write_io,
1008 .read_mem = palacios_host_dev_read_mem,
1009 .write_mem = palacios_host_dev_write_mem,
1010 .read_config = palacios_host_dev_read_conf,
1011 .write_config = palacios_host_dev_write_conf,
1012 .ack_irq = palacios_host_dev_ack_irq,
1017 int palacios_init_host_dev( void ) {
1018 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);