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
269 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
271 void __user *argp = (void __user *)arg;
273 struct palacios_host_device_user *dev = fp->private_data;
275 if (!dev->connected) {
280 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
282 struct palacios_host_dev_user_op op;
284 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
285 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
290 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
291 void *temp = kmalloc(op.len,GFP_KERNEL);
294 printk("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
298 if (v3_host_dev_read_guest_mem(dev->guestdev,
303 printk("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
308 if (copy_to_user(op.data,temp,op.len)) {
309 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
321 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
323 void *temp = kmalloc(op.len,GFP_KERNEL);
326 printk("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
330 if (copy_from_user(temp,op.data,op.len)) {
331 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
336 if (v3_host_dev_write_guest_mem(dev->guestdev,
341 printk("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
352 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
354 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
359 printk("palacios: unknown user request to host device \"%s\"\n",dev->url);
366 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
370 spin_lock_irqsave(&(dev->lock),f);
372 if (!(dev->waiting)) {
373 spin_unlock_irqrestore(&(dev->lock),f);
374 return 0; // no request available now
377 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
378 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
379 spin_unlock_irqrestore(&(dev->lock),f);
380 return -EFAULT; // failed to copy!
383 spin_unlock_irqrestore(&(dev->lock),f);
385 return 1; // have request for you
391 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
395 spin_lock_irqsave(&(dev->lock),f);
397 if (!(dev->waiting)) {
398 spin_unlock_irqrestore(&(dev->lock),f);
399 return 0; // no request available now
402 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
403 printk("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
404 spin_unlock_irqrestore(&(dev->lock),f);
405 return -EFAULT; // failed to copy!
408 spin_unlock_irqrestore(&(dev->lock),f);
410 return 1; // copied request for you
414 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
417 uint64_t user_datalen;
419 spin_lock_irqsave(&(dev->lock),f);
421 if (!(dev->waiting)) {
422 spin_unlock_irqrestore(&(dev->lock),f);
423 return 0; // no request outstanding, so we do not need a response!
426 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
427 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
428 spin_unlock_irqrestore(&(dev->lock),f);
429 return -EFAULT; // failed to copy!
432 if (palacios_resize_reqresp(&(dev->resp),user_datalen,0)) {
433 printk("palacios: unable to resize to accept request of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
434 spin_unlock_irqrestore(&(dev->lock),f);
438 if (copy_from_user(dev->resp, argp, user_datalen)) {
439 printk("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
440 spin_unlock_irqrestore(&(dev->lock),f);
441 return -EFAULT; // failed to copy!
444 // now have valid response!
447 // wake the palacios side up so that it sees it
448 cycle_response_request(dev);
450 spin_unlock_irqrestore(&(dev->lock),f);
457 printk("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
465 static struct file_operations host_dev_fops = {
466 .poll = host_dev_poll,
467 .release = host_dev_release,
468 .ioctl = host_dev_ioctl,
474 int connect_host_dev(struct v3_guest * guest, char *url)
476 struct palacios_host_device_user *dev;
477 unsigned long f1, f2;
480 // currently only support user: types:
481 if (strncasecmp(url,"user:",5)) {
482 printk("palacios: do not currently support host devices of type in \"%s\"\n",url);
486 printk("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
488 // We will scan the list looking for the relevant
489 // URL. If we don't find it after a while, we give up
491 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
492 spin_lock_irqsave(&(guest->hostdev.lock),f1);
493 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
494 if (!strncasecmp(url,dev->url,MAX_URL)) {
496 spin_lock_irqsave(&(dev->lock),f2);
497 if (dev->connected) {
498 printk("palacios: device for \"%s\" is already connected!\n",url);
499 spin_unlock_irqrestore(&(dev->lock),f2);
500 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
503 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
505 printk("palacios: cannot create fd for device \"%s\"\n",url);
506 spin_unlock_irqrestore(&(dev->lock),f2);
507 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
520 printk("palacios: connected fd for device \"%s\"\n",url);
521 spin_unlock_irqrestore(&(dev->lock),f2);
522 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
525 spin_unlock_irqrestore(&(dev->lock),f2);
528 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
530 ssleep(RENDEZVOUS_RETRY_SECS);
533 printk("palacios: timeout waiting for connection for device \"%s\"",url);
546 /***************************************************************************************
548 Following this is the implementation of the palacios->host interface
550 **************************************************************************************/
552 static v3_host_dev_t palacios_host_dev_open(char *url,
555 void *host_priv_data)
557 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
558 struct palacios_host_device_user *dev;
563 I will create the device in the list and then wait
564 for the user side to attach
568 if (strncasecmp(url,"user:",5)) {
569 printk("palacios: do not currently support devices of type in \"%s\"\n",url);
573 // Check to see if a device of this url already exists, which would be ugly
574 spin_lock_irqsave(&(guest->hostdev.lock),f1);
575 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
576 if (!strncasecmp(url,dev->url,MAX_URL)) {
578 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
579 printk("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
583 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
586 printk("palacios: creating host device \"%s\"\n",url);
588 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
591 printk("palacios: cannot allocate for host device \"%s\"\n",url);
595 memset(dev,0,sizeof(struct palacios_host_device_user));
597 strncpy(dev->url,url,MAX_URL);
603 spin_lock_init(&(dev->lock));
605 init_waitqueue_head(&(dev->user_wait_queue));
606 init_waitqueue_head(&(dev->host_wait_queue));
608 printk("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
610 // Insert ourselves into the list
611 spin_lock_irqsave(&(guest->hostdev.lock),f1);
612 list_add(&(dev->node),&(guest->hostdev.devs));
613 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
616 // Now wait until we are noticed!
617 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
618 spin_lock_irqsave(&(dev->lock),f2);
620 printk("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
621 spin_unlock_irqrestore(&(dev->lock),f2);
624 spin_unlock_irqrestore(&(dev->lock),f2);
625 ssleep(RENDEZVOUS_RETRY_SECS);
628 printk("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
630 // get us out of the list
631 spin_lock_irqsave(&(guest->hostdev.lock),f1);
632 list_del(&(dev->node));
633 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
635 palacios_host_dev_user_free(dev);
640 static int palacios_host_dev_close(v3_host_dev_t hostdev)
642 unsigned long f1, f2;
644 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
646 printk("palacios: closing host device \"%s\"\n",dev->url);
648 spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
650 spin_lock_irqsave(&(dev->lock),f2);
652 if (dev->connected) {
654 // After this, any user side request will return -EFAULT
657 list_del(&(dev->node));
659 spin_unlock_irqrestore(&(dev->lock),f2);
660 spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
662 palacios_host_dev_user_free(dev);
670 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
675 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
679 spin_lock_irqsave(&(dev->lock),f);
682 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);
683 spin_unlock_irqrestore(&(dev->lock),f);
687 if (!dev->connected) {
688 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
689 spin_unlock_irqrestore(&(dev->lock),f);
693 // resize request and response in case they will need it
694 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
696 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
698 dev->req->op_len=len;
700 dev->req->conf_addr=0;
701 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
705 spin_unlock_irqrestore(&(dev->lock),f);
707 // hand over to the user space and wait for it to respond
708 cycle_request_response(dev);
710 // We're back! So now we'll hand the response back to Palacios
712 spin_lock_irqsave(&(dev->lock),f);
714 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
716 memcpy(dest,dev->resp->data, op_len);
718 spin_unlock_irqrestore(&(dev->lock),f);
723 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
728 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
732 spin_lock_irqsave(&(dev->lock),f);
735 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);
736 spin_unlock_irqrestore(&(dev->lock),f);
739 if (!dev->connected) {
740 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
741 spin_unlock_irqrestore(&(dev->lock),f);
745 // resize request and response in case they will need it
746 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
748 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
750 dev->req->op_len=len;
752 dev->req->conf_addr=0;
753 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
757 spin_unlock_irqrestore(&(dev->lock),f);
759 // hand over to the user space and wait for it to respond
760 cycle_request_response(dev);
762 // We're back! So now we'll hand the response back to Palacios
764 spin_lock_irqsave(&(dev->lock),f);
766 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
768 memcpy(dest,dev->resp->data, op_len);
770 spin_unlock_irqrestore(&(dev->lock),f);
775 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
780 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
784 spin_lock_irqsave(&(dev->lock),f);
787 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);
788 spin_unlock_irqrestore(&(dev->lock),f);
791 if (!dev->connected) {
792 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
793 spin_unlock_irqrestore(&(dev->lock),f);
797 // resize request and response in case they will need it
798 palacios_resize_reqresp(&(dev->req),0,0); // request doesn't carry data
800 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
802 dev->req->op_len=len;
804 dev->req->conf_addr=offset;
805 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
809 spin_unlock_irqrestore(&(dev->lock),f);
811 // hand over to the user space and wait for it to respond
812 cycle_request_response(dev);
814 // We're back! So now we'll hand the response back to Palacios
816 spin_lock_irqsave(&(dev->lock),f);
818 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
820 memcpy(dest,dev->resp->data, op_len);
822 spin_unlock_irqrestore(&(dev->lock),f);
828 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
833 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
837 spin_lock_irqsave(&(dev->lock),f);
840 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);
841 spin_unlock_irqrestore(&(dev->lock),f);
844 if (!dev->connected) {
845 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
846 spin_unlock_irqrestore(&(dev->lock),f);
850 // resize request and response in case they will need it
851 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
853 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
855 dev->req->op_len=len;
857 dev->req->conf_addr=0;
858 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
860 memcpy(dev->req->data,src,len);
864 spin_unlock_irqrestore(&(dev->lock),f);
866 // hand over to the user space and wait for it to respond
867 cycle_request_response(dev);
869 // We're back! So now we'll hand the response back to Palacios
871 spin_lock_irqsave(&(dev->lock),f);
873 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
875 spin_unlock_irqrestore(&(dev->lock),f);
881 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
886 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
890 spin_lock_irqsave(&(dev->lock),f);
893 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);
894 spin_unlock_irqrestore(&(dev->lock),f);
897 if (!dev->connected) {
898 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
899 spin_unlock_irqrestore(&(dev->lock),f);
903 // resize request and response in case they will need it
904 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
906 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
908 dev->req->op_len=len;
910 dev->req->conf_addr=0;
911 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
913 memcpy(dev->req->data,src,len);
917 spin_unlock_irqrestore(&(dev->lock),f);
919 // hand over to the user space and wait for it to respond
920 cycle_request_response(dev);
922 // We're back! So now we'll hand the response back to Palacios
924 spin_lock_irqsave(&(dev->lock),f);
926 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
928 spin_unlock_irqrestore(&(dev->lock),f);
934 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
942 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
947 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
951 spin_lock_irqsave(&(dev->lock),f);
954 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);
955 spin_unlock_irqrestore(&(dev->lock),f);
958 if (!dev->connected) {
959 printk("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
960 spin_unlock_irqrestore(&(dev->lock),f);
964 // resize request and response in case they will need it
965 palacios_resize_reqresp(&(dev->req),len,0); // make room for data
967 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
969 dev->req->op_len=len;
971 dev->req->conf_addr=offset;
972 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
974 memcpy(dev->req->data,src,len);
978 spin_unlock_irqrestore(&(dev->lock),f);
980 // hand over to the user space and wait for it to respond
981 cycle_request_response(dev);
983 // We're back! So now we'll hand the response back to Palacios
985 spin_lock_irqsave(&(dev->lock),f);
987 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
989 spin_unlock_irqrestore(&(dev->lock),f);
999 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1000 .open = palacios_host_dev_open,
1001 .close = palacios_host_dev_close,
1002 .read_io = palacios_host_dev_read_io,
1003 .write_io = palacios_host_dev_write_io,
1004 .read_mem = palacios_host_dev_read_mem,
1005 .write_mem = palacios_host_dev_write_mem,
1006 .read_config = palacios_host_dev_read_conf,
1007 .write_config = palacios_host_dev_write_conf,
1008 .ack_irq = palacios_host_dev_ack_irq,
1013 int palacios_init_host_dev( void ) {
1014 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);