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 #define SHALLOW_DEBUG 0
119 #define DEEP_DEBUG_PRINT(fmt, args...) printk((fmt), ##args)
121 #define DEEP_DEBUG_PRINT(fmt, args...)
125 #define SHALLOW_DEBUG_PRINT(fmt, args...) printk((fmt), ##args)
127 #define SHALLOW_DEBUG_PRINT(fmt, args...)
131 #define ERROR(fmt, args...) printk((fmt), ##args)
132 #define INFO(fmt, args...) printk((fmt), ##args)
134 struct palacios_host_device_user {
136 int connected; // is the user space connected to this?
137 int waiting; // am I waiting for a user-space response?
139 int fd; // what is the user space fd?
141 char url[MAX_URL]; // what is the url describing the device
143 v3_guest_dev_t guestdev; // what is the palacios-side device
145 wait_queue_head_t user_wait_queue; // user space processes waiting on us (should be only one)
146 wait_queue_head_t host_wait_queue; // host threads (should only be one) waiting on user space
148 struct v3_guest *guest; // my guest
149 struct palacios_host_dev_host_request_response *req; // curent request
150 struct palacios_host_dev_host_request_response *resp; // curent response
152 struct list_head node; // for adding me to the list of hostdevs this VM has
156 /**************************************************************************************
158 *************************************************************************************/
160 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
175 // Is this structure big enough for the data_size we will use?
177 // THIS FUNCTION CAN BE CALLED WHILE INTERRUPTS ARE OFF
179 static int palacios_bigenough_reqresp(struct palacios_host_dev_host_request_response *r, uint64_t data_size)
184 if (((r->len)-sizeof(struct palacios_host_dev_host_request_response)) < data_size) {
193 // Resize a request/response structure so that it will fit data_size bytes
195 // At the end of this, *r->len >= sizeof(struct)+data_size
197 // THIS FUNCTION MAY SLEEP AS IT CALLS KMALLOC
198 // DO NOT CALL IT WHILE HOLDING A SPIN LOCK WITH INTERRUPTS OFF
200 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
203 DEEP_DEBUG_PRINT("palacios: hostdev: resize 0x%p to %llu\n",*r,data_size);
207 DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n");
208 *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
209 DEEP_DEBUG_PRINT("palacios: hostdev: kmalloc done\n");
211 ERROR("palacios: hostdev: failed to allocate\n");
214 (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
215 DEEP_DEBUG_PRINT("palacios: hostdev: allocated\n");
219 //let it go if it's big enough
220 uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
222 if (data_size<=cur_len) {
224 DEEP_DEBUG_PRINT("palacios: hostdev: size ok\n");
227 struct palacios_host_dev_host_request_response *new;
233 new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
235 ERROR("palacios: hostdev: failed to reallocate\n");
238 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
240 memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
241 new->data_len=(*r)->data_len;
245 DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n");
252 static void cycle_request_response(struct palacios_host_device_user *dev)
254 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response\n");
255 // wake up user side so that polls fall through
256 wake_up_interruptible(&(dev->user_wait_queue));
257 // put us to sleep until the user side wakes us up
258 while (wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0)) != 0) {}
260 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response - done\n");
263 static void cycle_response_request(struct palacios_host_device_user *dev)
265 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request\n");
267 wake_up_interruptible(&(dev->host_wait_queue));
268 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request - done\n");
272 /*********************************************************************************************
274 Interface to user space
276 *********************************************************************************************/
280 static unsigned int host_dev_poll(struct file * filp,
281 struct poll_table_struct * poll_tb)
284 struct palacios_host_device_user * dev = filp->private_data;
287 SHALLOW_DEBUG_PRINT("palacios: hostdev: poll\n");
289 if (!dev->connected) {
290 ERROR("palcios: hostdev: poll on unconnected device\n");
294 spin_lock_irqsave(&(dev->lock),f);
297 // Yes, we have a request if you want it!
298 spin_unlock_irqrestore(&(dev->lock),f);
299 DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n");
300 return POLLIN | POLLRDNORM;
303 // No request yet, so we need to wait for one to show up.
305 // register ourselves on the user wait queue
306 poll_wait(filp, &(dev->user_wait_queue), poll_tb);
308 spin_unlock_irqrestore(&(dev->lock),f);
310 DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
311 // We will get called again when that queue is woken up
317 static int host_dev_release(struct inode * i, struct file * filp)
319 struct palacios_host_device_user *dev = filp->private_data;
322 INFO("palacios: user side is closing host device \"%s\"\n",dev->url);
324 spin_lock_irqsave(&(dev->lock), f);
326 spin_unlock_irqrestore(&(dev->lock), f);
328 // it is the palacios->host interface's responsibility to ignore
329 // reads/writes until connected is true
335 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
337 void __user *argp = (void __user *)arg;
339 struct palacios_host_device_user *dev = fp->private_data;
341 DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
344 if (!dev->connected) {
345 ERROR("palacios: hostdev: ioctl on unconnected device\n");
350 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
352 struct palacios_host_dev_user_op op;
354 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
355 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
359 DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
362 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
363 void *temp = kmalloc(op.len,GFP_KERNEL);
365 DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
368 ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
372 if (v3_host_dev_read_guest_mem(dev->guestdev,
377 ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
382 if (copy_to_user(op.data,temp,op.len)) {
383 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
395 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
398 DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
400 temp = kmalloc(op.len,GFP_KERNEL);
403 ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
407 if (copy_from_user(temp,op.data,op.len)) {
408 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
413 if (v3_host_dev_write_guest_mem(dev->guestdev,
418 ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
429 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
431 DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
433 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
438 ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
445 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
450 DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
452 spin_lock_irqsave(&(dev->lock),f);
454 if (!(dev->waiting)) {
455 spin_unlock_irqrestore(&(dev->lock),f);
456 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
457 schedule(); // avoid livelock for polling user space process SUSPICOUS
458 return 0; // no request available now
461 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
462 spin_unlock_irqrestore(&(dev->lock),f);
463 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
464 return -EFAULT; // failed to copy!
468 spin_unlock_irqrestore(&(dev->lock),f);
470 DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
472 return 1; // have request for you
478 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
482 spin_lock_irqsave(&(dev->lock),f);
484 DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
486 if (!(dev->waiting) || !(dev->req)) {
487 spin_unlock_irqrestore(&(dev->lock),f);
488 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
489 return 0; // no request available now
493 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
494 spin_unlock_irqrestore(&(dev->lock),f);
495 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
496 return -EFAULT; // failed to copy!
499 spin_unlock_irqrestore(&(dev->lock),f);
501 DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
503 return 1; // copied request for you
507 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
510 uint64_t user_datalen;
513 spin_lock_irqsave(&(dev->lock),f);
515 DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
517 if (!(dev->waiting)) {
518 spin_unlock_irqrestore(&(dev->lock),f);
519 ERROR("palacios: hostdev: no matching request for pushed response\n");
520 return 0; // no request outstanding, so we do not need a response!
523 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
524 spin_unlock_irqrestore(&(dev->lock),f);
525 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
526 return -EFAULT; // failed to copy!
529 if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) {
531 spin_unlock_irqrestore(&(dev->lock),f);
532 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
536 if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
538 // we drop the lock, turn on interrupts, resize, and then retry
539 DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
541 spin_unlock_irqrestore(&(dev->lock),f);
543 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
544 ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
547 // reacquire the lock
548 // There shouldn't be a race here, since there should
549 // be exactly one user space thread giving us a response for this device
550 // and it is blocked waiting for us to finish
551 spin_lock_irqsave(&(dev->lock),f);
552 DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
556 //We only copy data_len bytes from user, but we will
557 //overwrite the len field, so we preserve and then restore
558 old_len = dev->resp->len;
559 if (copy_from_user(dev->resp, argp, user_datalen)) {
560 dev->resp->len=old_len;
561 spin_unlock_irqrestore(&(dev->lock),f);
562 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
563 return -EFAULT; // failed to copy!
565 dev->resp->len=old_len;
567 DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
568 // now have valid response!
571 spin_unlock_irqrestore(&(dev->lock),f);
573 // wake the palacios side up so that it sees it
574 cycle_response_request(dev);
581 ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
591 static struct file_operations host_dev_fops = {
592 .poll = host_dev_poll,
593 .release = host_dev_release,
594 .ioctl = host_dev_ioctl,
600 int connect_host_dev(struct v3_guest * guest, char *url)
602 struct palacios_host_device_user *dev;
603 unsigned long f1, f2;
606 // currently only support user: types:
607 if (strncasecmp(url,"user:",5)) {
608 ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
612 INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
614 // We will scan the list looking for the relevant
615 // URL. If we don't find it after a while, we give up
617 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
618 spin_lock_irqsave(&(guest->hostdev.lock),f1);
619 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
620 if (!strncasecmp(url,dev->url,MAX_URL)) {
622 spin_lock_irqsave(&(dev->lock),f2);
623 if (dev->connected) {
624 ERROR("palacios: device for \"%s\" is already connected!\n",url);
625 spin_unlock_irqrestore(&(dev->lock),f2);
626 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
629 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
631 ERROR("palacios: cannot create fd for device \"%s\"\n",url);
632 spin_unlock_irqrestore(&(dev->lock),f2);
633 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
646 INFO("palacios: connected fd for device \"%s\"\n",url);
647 spin_unlock_irqrestore(&(dev->lock),f2);
648 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
651 spin_unlock_irqrestore(&(dev->lock),f2);
654 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
656 ssleep(RENDEZVOUS_RETRY_SECS);
659 ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
672 /***************************************************************************************
674 Following this is the implementation of the palacios->host interface
676 **************************************************************************************/
678 static v3_host_dev_t palacios_host_dev_open(char *url,
681 void *host_priv_data)
683 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
684 struct palacios_host_device_user *dev;
689 I will create the device in the list and then wait
690 for the user side to attach
694 if (strncasecmp(url,"user:",5)) {
695 ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
699 // Check to see if a device of this url already exists, which would be ugly
700 spin_lock_irqsave(&(guest->hostdev.lock),f1);
701 list_for_each_entry(dev,&(guest->hostdev.devs), node) {
702 if (!strncasecmp(url,dev->url,MAX_URL)) {
704 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
705 ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
709 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
712 INFO("palacios: creating host device \"%s\"\n",url);
714 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
717 ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
721 memset(dev,0,sizeof(struct palacios_host_device_user));
723 strncpy(dev->url,url,MAX_URL);
729 spin_lock_init(&(dev->lock));
731 init_waitqueue_head(&(dev->user_wait_queue));
732 init_waitqueue_head(&(dev->host_wait_queue));
734 INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
736 // Insert ourselves into the list
737 spin_lock_irqsave(&(guest->hostdev.lock),f1);
738 list_add(&(dev->node),&(guest->hostdev.devs));
739 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
742 // Now wait until we are noticed!
743 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
744 spin_lock_irqsave(&(dev->lock),f2);
746 INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
747 spin_unlock_irqrestore(&(dev->lock),f2);
750 spin_unlock_irqrestore(&(dev->lock),f2);
751 ssleep(RENDEZVOUS_RETRY_SECS);
754 ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
756 // get us out of the list
757 spin_lock_irqsave(&(guest->hostdev.lock),f1);
758 list_del(&(dev->node));
759 spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
761 palacios_host_dev_user_free(dev);
766 static int palacios_host_dev_close(v3_host_dev_t hostdev)
768 unsigned long f1, f2;
770 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
772 INFO("palacios: closing host device \"%s\"\n",dev->url);
774 spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
776 spin_lock_irqsave(&(dev->lock),f2);
778 if (dev->connected) {
780 // After this, any user side request will return -EFAULT
783 list_del(&(dev->node));
785 spin_unlock_irqrestore(&(dev->lock),f2);
786 spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
788 palacios_host_dev_user_free(dev);
796 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
801 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
805 DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
808 spin_lock_irqsave(&(dev->lock),f);
811 spin_unlock_irqrestore(&(dev->lock),f);
812 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);
816 if (!dev->connected) {
817 spin_unlock_irqrestore(&(dev->lock),f);
818 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
823 // resize request (no data)
824 if (!palacios_bigenough_reqresp(dev->req,0)) {
826 // we drop the lock, turn on interrupts, resize, and then retry
827 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
829 spin_unlock_irqrestore(&(dev->lock),f);
831 if (palacios_resize_reqresp(&(dev->req),0,0)) {
832 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
835 // reacquire the lock
836 // There shouldn't be a race here since there should not be another
837 // request from palacios until this one finishes
838 spin_lock_irqsave(&(dev->lock),f);
839 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
844 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
846 dev->req->op_len=len;
848 dev->req->conf_addr=0;
849 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
853 spin_unlock_irqrestore(&(dev->lock),f);
855 // hand over to the user space and wait for it to respond
856 cycle_request_response(dev);
858 // We're back! So now we'll hand the response back to Palacios
860 spin_lock_irqsave(&(dev->lock),f);
862 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
864 memcpy(dest,dev->resp->data, op_len);
866 spin_unlock_irqrestore(&(dev->lock),f);
871 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
876 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
880 DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa);
882 spin_lock_irqsave(&(dev->lock),f);
885 spin_unlock_irqrestore(&(dev->lock),f);
886 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);
889 if (!dev->connected) {
890 spin_unlock_irqrestore(&(dev->lock),f);
891 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
895 // resize request (no data)
896 if (!palacios_bigenough_reqresp(dev->req,0)) {
898 // we drop the lock, turn on interrupts, resize, and then retry
899 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
901 spin_unlock_irqrestore(&(dev->lock),f);
903 if (palacios_resize_reqresp(&(dev->req),0,0)) {
904 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
907 // reacquire the lock
908 // There shouldn't be a race here since there should not be another
909 // request from palacios until this one finishes
910 spin_lock_irqsave(&(dev->lock),f);
911 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
915 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
917 dev->req->op_len=len;
919 dev->req->conf_addr=0;
920 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
924 spin_unlock_irqrestore(&(dev->lock),f);
926 // hand over to the user space and wait for it to respond
927 cycle_request_response(dev);
929 // We're back! So now we'll hand the response back to Palacios
931 spin_lock_irqsave(&(dev->lock),f);
933 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
935 memcpy(dest,dev->resp->data, op_len);
937 spin_unlock_irqrestore(&(dev->lock),f);
942 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
947 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
951 DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
953 spin_lock_irqsave(&(dev->lock),f);
956 spin_unlock_irqrestore(&(dev->lock),f);
957 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);
960 if (!dev->connected) {
961 spin_unlock_irqrestore(&(dev->lock),f);
962 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
966 // resize request (no data)
967 if (!palacios_bigenough_reqresp(dev->req,0)) {
969 // we drop the lock, turn on interrupts, resize, and then retry
970 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
972 spin_unlock_irqrestore(&(dev->lock),f);
974 if (palacios_resize_reqresp(&(dev->req),0,0)) {
975 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
978 // reacquire the lock
979 // There shouldn't be a race here since there should not be another
980 // request from palacios until this one finishes
981 spin_lock_irqsave(&(dev->lock),f);
982 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
986 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
988 dev->req->op_len=len;
990 dev->req->conf_addr=offset;
991 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
995 spin_unlock_irqrestore(&(dev->lock),f);
997 // hand over to the user space and wait for it to respond
998 cycle_request_response(dev);
1000 // We're back! So now we'll hand the response back to Palacios
1002 spin_lock_irqsave(&(dev->lock),f);
1004 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1006 memcpy(dest,dev->resp->data, op_len);
1008 spin_unlock_irqrestore(&(dev->lock),f);
1014 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1019 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1023 DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1025 spin_lock_irqsave(&(dev->lock),f);
1028 spin_unlock_irqrestore(&(dev->lock),f);
1029 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);
1032 if (!dev->connected) {
1033 spin_unlock_irqrestore(&(dev->lock),f);
1034 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1039 if (!palacios_bigenough_reqresp(dev->req,len)) {
1041 // we drop the lock, turn on interrupts, resize, and then retry
1042 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1044 spin_unlock_irqrestore(&(dev->lock),f);
1046 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1047 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1050 // reacquire the lock
1051 // There shouldn't be a race here since there should not be another
1052 // request from palacios until this one finishes
1053 spin_lock_irqsave(&(dev->lock),f);
1054 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1058 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1059 dev->req->port=port;
1060 dev->req->op_len=len;
1062 dev->req->conf_addr=0;
1063 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1065 memcpy(dev->req->data,src,len);
1069 spin_unlock_irqrestore(&(dev->lock),f);
1071 // hand over to the user space and wait for it to respond
1072 cycle_request_response(dev);
1074 // We're back! So now we'll hand the response back to Palacios
1076 spin_lock_irqsave(&(dev->lock),f);
1078 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1080 spin_unlock_irqrestore(&(dev->lock),f);
1086 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1091 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1095 DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1097 spin_lock_irqsave(&(dev->lock),f);
1100 spin_unlock_irqrestore(&(dev->lock),f);
1101 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);
1104 if (!dev->connected) {
1105 spin_unlock_irqrestore(&(dev->lock),f);
1106 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1111 if (!palacios_bigenough_reqresp(dev->req,len)) {
1113 // we drop the lock, turn on interrupts, resize, and then retry
1114 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1116 spin_unlock_irqrestore(&(dev->lock),f);
1118 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1119 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1122 // reacquire the lock
1123 // There shouldn't be a race here since there should not be another
1124 // request from palacios until this one finishes
1125 spin_lock_irqsave(&(dev->lock),f);
1126 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1130 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1132 dev->req->op_len=len;
1134 dev->req->conf_addr=0;
1135 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1137 memcpy(dev->req->data,src,len);
1141 spin_unlock_irqrestore(&(dev->lock),f);
1143 // hand over to the user space and wait for it to respond
1144 cycle_request_response(dev);
1146 // We're back! So now we'll hand the response back to Palacios
1148 spin_lock_irqsave(&(dev->lock),f);
1150 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1152 spin_unlock_irqrestore(&(dev->lock),f);
1160 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1165 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1169 DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1171 spin_lock_irqsave(&(dev->lock),f);
1174 spin_unlock_irqrestore(&(dev->lock),f);
1175 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);
1178 if (!dev->connected) {
1179 spin_unlock_irqrestore(&(dev->lock),f);
1180 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1185 if (!palacios_bigenough_reqresp(dev->req,len)) {
1187 // we drop the lock, turn on interrupts, resize, and then retry
1188 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1190 spin_unlock_irqrestore(&(dev->lock),f);
1192 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1193 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1196 // reacquire the lock
1197 // There shouldn't be a race here since there should not be another
1198 // request from palacios until this one finishes
1199 spin_lock_irqsave(&(dev->lock),f);
1200 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1204 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1206 dev->req->op_len=len;
1208 dev->req->conf_addr=offset;
1209 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1211 memcpy(dev->req->data,src,len);
1215 spin_unlock_irqrestore(&(dev->lock),f);
1217 // hand over to the user space and wait for it to respond
1218 cycle_request_response(dev);
1220 // We're back! So now we'll hand the response back to Palacios
1222 spin_lock_irqsave(&(dev->lock),f);
1224 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1226 spin_unlock_irqrestore(&(dev->lock),f);
1232 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1242 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1243 .open = palacios_host_dev_open,
1244 .close = palacios_host_dev_close,
1245 .read_io = palacios_host_dev_read_io,
1246 .write_io = palacios_host_dev_write_io,
1247 .read_mem = palacios_host_dev_read_mem,
1248 .write_mem = palacios_host_dev_write_mem,
1249 .read_config = palacios_host_dev_read_conf,
1250 .write_config = palacios_host_dev_write_conf,
1251 .ack_irq = palacios_host_dev_ack_irq,
1256 int palacios_init_host_dev( void )
1258 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);