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 "iface-host-dev.h"
21 #include "linux-exts.h"
25 There are two things in this file:
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
33 Palacios opens a host device by issuing something like this:
35 palacios_host_dev_open( impl="user:foo" busclass=pci, opaque )
37 This will attempt to rendezvous with the user space device The
38 rendevzous retry and timeout periods can be set below.
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
44 The user space gets a file descriptor like this:
46 int vmfd = open("/dev/v3-vmX",...);
48 int devfd = ioctl(vmfd,V3_HOST_DEV_CONNECT,"user:foo");
50 This will attempt to rendezvous with the host side.
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.
57 struct palacios_host_dev_user_op op;
60 op.type = PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST;
63 ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL, &op);
65 // return value is # bytes read or written; or 0 if irq injected
66 // negative value is error
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.
79 What this looks like is:
81 poll(...devfd for read...) or select(...devfd for read...)
83 if (devfd is marked readable) {
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
89 struct palacios_host_dev_host_request_response *req;
91 req = allocate req to be at least size bytes long
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
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
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
105 Note that the current model has deferred rendezvous and allows
106 for user-side device disconnection and reconnection. It is important
107 to note that this implementation does NOT deal with state discrepency
108 between the palacios-side and the user-side. For example, a user-side
109 device can disconnect, a palacios-side request can then fail, and
110 when the user-side device reconnects, it is unaware of this failure.
115 struct palacios_host_dev {
117 struct list_head devs;
123 #define RENDEZVOUS_WAIT_SECS 60
124 #define RENDEZVOUS_RETRY_SECS 1
127 #define SHALLOW_DEBUG 0
130 #define DEEP_DEBUG_PRINT(fmt, args...) DEBUG((fmt), ##args)
132 #define DEEP_DEBUG_PRINT(fmt, args...)
136 #define SHALLOW_DEBUG_PRINT(fmt, args...) INFO((fmt), ##args)
138 #define SHALLOW_DEBUG_PRINT(fmt, args...)
142 struct palacios_host_device_user {
144 int connected; // is the user space connected to this?
145 int waiting; // am I waiting for a user-space response?
147 int fd; // what is the user space fd?
149 char url[MAX_URL]; // what is the url describing the device
151 v3_guest_dev_t guestdev; // what is the palacios-side device
153 wait_queue_head_t user_wait_queue; // user space processes waiting on us (should be only one)
154 wait_queue_head_t host_wait_queue; // host threads (should only be one) waiting on user space
156 struct v3_guest *guest; // my guest
157 struct palacios_host_dev_host_request_response *req; // curent request
158 struct palacios_host_dev_host_request_response *resp; // curent response
160 struct list_head node; // for adding me to the list of hostdevs this VM has
164 /**************************************************************************************
166 *************************************************************************************/
168 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
171 palacios_free(dev->req);
175 palacios_free(dev->resp);
183 // Is this structure big enough for the data_size we will use?
185 // THIS FUNCTION CAN BE CALLED WHILE INTERRUPTS ARE OFF
187 static int palacios_bigenough_reqresp(struct palacios_host_dev_host_request_response *r, uint64_t data_size)
192 if (((r->len)-sizeof(struct palacios_host_dev_host_request_response)) < data_size) {
201 // Resize a request/response structure so that it will fit data_size bytes
203 // At the end of this, *r->len >= sizeof(struct)+data_size
205 // THIS FUNCTION MAY SLEEP AS IT CALLS KMALLOC
206 // DO NOT CALL IT WHILE HOLDING A SPIN LOCK WITH INTERRUPTS OFF
208 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
211 DEEP_DEBUG_PRINT("palacios: hostdev: resize 0x%p to %llu\n",*r,data_size);
215 DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n");
216 *r = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size);
217 DEEP_DEBUG_PRINT("palacios: hostdev: palacios_alloc done\n");
219 ERROR("palacios: hostdev: failed to allocate\n");
222 (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
223 DEEP_DEBUG_PRINT("palacios: hostdev: allocated\n");
227 //let it go if it's big enough
228 uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
230 if (data_size<=cur_len) {
232 DEEP_DEBUG_PRINT("palacios: hostdev: size ok\n");
235 struct palacios_host_dev_host_request_response *new;
241 new = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size);
243 ERROR("palacios: hostdev: failed to reallocate\n");
246 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
248 memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
249 new->data_len=(*r)->data_len;
253 DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n");
260 static void cycle_request_response(struct palacios_host_device_user *dev)
262 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response\n");
263 // wake up user side so that polls fall through
264 wake_up_interruptible(&(dev->user_wait_queue));
265 // put us to sleep until the user side wakes us up
266 while (wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0)) != 0) {}
268 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response - done\n");
271 static void cycle_response_request(struct palacios_host_device_user *dev)
273 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request\n");
275 wake_up_interruptible(&(dev->host_wait_queue));
276 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request - done\n");
280 /*********************************************************************************************
282 Interface to user space
284 *********************************************************************************************/
288 static unsigned int host_dev_poll(struct file * filp,
289 struct poll_table_struct * poll_tb)
292 struct palacios_host_device_user * dev = filp->private_data;
295 SHALLOW_DEBUG_PRINT("palacios: hostdev: poll\n");
297 if (!dev->connected) {
298 ERROR("palcios: hostdev: poll on unconnected device\n");
302 spin_lock_irqsave(&(dev->lock),f);
305 // Yes, we have a request if you want it!
306 spin_unlock_irqrestore(&(dev->lock),f);
307 DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n");
308 return POLLIN | POLLRDNORM;
311 // No request yet, so we need to wait for one to show up.
313 // register ourselves on the user wait queue
314 poll_wait(filp, &(dev->user_wait_queue), poll_tb);
316 spin_unlock_irqrestore(&(dev->lock),f);
318 DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
319 // We will get called again when that queue is woken up
325 static int host_dev_release(struct inode * i, struct file * filp)
327 struct palacios_host_device_user *dev = filp->private_data;
330 INFO("palacios: user side is closing host device \"%s\"\n",dev->url);
332 spin_lock_irqsave(&(dev->lock), f);
334 spin_unlock_irqrestore(&(dev->lock), f);
336 // it is the palacios->host interface's responsibility to ignore
337 // reads/writes until connected is true
342 static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg)
344 void __user *argp = (void __user *)arg;
346 struct palacios_host_device_user *dev = fp->private_data;
348 DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
351 if (!dev->connected) {
352 ERROR("palacios: hostdev: ioctl on unconnected device\n");
357 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
359 struct palacios_host_dev_user_op op;
361 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
362 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
366 DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
369 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
370 void *temp = palacios_alloc(op.len);
372 DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
375 ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
379 if (v3_host_dev_read_guest_mem(dev,
384 ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
389 if (copy_to_user(op.data,temp,op.len)) {
390 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
402 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
405 DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
407 temp = palacios_alloc(op.len);
410 ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
414 if (copy_from_user(temp,op.data,op.len)) {
415 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
420 if (v3_host_dev_write_guest_mem(dev,
425 ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
436 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
438 DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
440 return v3_host_dev_raise_irq(dev, dev->guestdev, op.irq);
445 ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
452 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
457 DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
459 spin_lock_irqsave(&(dev->lock),f);
461 if (!(dev->waiting)) {
462 spin_unlock_irqrestore(&(dev->lock),f);
463 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
464 schedule(); // avoid livelock for polling user space process SUSPICOUS
465 return 0; // no request available now
468 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
469 spin_unlock_irqrestore(&(dev->lock),f);
470 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
471 return -EFAULT; // failed to copy!
475 spin_unlock_irqrestore(&(dev->lock),f);
477 DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
479 return 1; // have request for you
485 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
489 spin_lock_irqsave(&(dev->lock),f);
491 DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
493 if (!(dev->waiting) || !(dev->req)) {
494 spin_unlock_irqrestore(&(dev->lock),f);
495 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
496 return 0; // no request available now
500 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
501 spin_unlock_irqrestore(&(dev->lock),f);
502 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
503 return -EFAULT; // failed to copy!
506 spin_unlock_irqrestore(&(dev->lock),f);
508 DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
510 return 1; // copied request for you
514 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
517 uint64_t user_datalen;
520 spin_lock_irqsave(&(dev->lock),f);
522 DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
524 if (!(dev->waiting)) {
525 spin_unlock_irqrestore(&(dev->lock),f);
526 ERROR("palacios: hostdev: no matching request for pushed response\n");
527 return 0; // no request outstanding, so we do not need a response!
530 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
531 spin_unlock_irqrestore(&(dev->lock),f);
532 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
533 return -EFAULT; // failed to copy!
536 if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) {
538 spin_unlock_irqrestore(&(dev->lock),f);
539 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
543 if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
545 // we drop the lock, turn on interrupts, resize, and then retry
546 DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
548 spin_unlock_irqrestore(&(dev->lock),f);
550 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
551 ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
554 // reacquire the lock
555 // There shouldn't be a race here, since there should
556 // be exactly one user space thread giving us a response for this device
557 // and it is blocked waiting for us to finish
558 spin_lock_irqsave(&(dev->lock),f);
559 DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
563 //We only copy data_len bytes from user, but we will
564 //overwrite the len field, so we preserve and then restore
565 old_len = dev->resp->len;
566 if (copy_from_user(dev->resp, argp, user_datalen)) {
567 dev->resp->len=old_len;
568 spin_unlock_irqrestore(&(dev->lock),f);
569 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
570 return -EFAULT; // failed to copy!
572 dev->resp->len=old_len;
574 DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
575 // now have valid response!
578 spin_unlock_irqrestore(&(dev->lock),f);
580 // wake the palacios side up so that it sees it
581 cycle_response_request(dev);
588 ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
595 static struct file_operations host_dev_fops = {
596 .poll = host_dev_poll,
597 .release = host_dev_release,
598 .compat_ioctl = host_dev_ioctl,
599 .unlocked_ioctl = host_dev_ioctl,
604 static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data)
606 void __user * argp = (void __user *)arg;
608 struct palacios_host_dev * host_dev = priv_data;
609 struct palacios_host_device_user *dev;
610 unsigned long f1, f2;
615 if (copy_from_user(url, argp, MAX_URL)) {
616 ERROR("copy from user error getting url for host device connect...\n");
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);
626 INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
628 // We will scan the list looking for the relevant
629 // URL. If we don't find it after a while, we give up
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)) {
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);
643 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 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);
653 palacios_free(dev->req);
657 palacios_free(dev->resp);
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);
665 spin_unlock_irqrestore(&(dev->lock),f2);
668 spin_unlock_irqrestore(&(host_dev->lock),f1);
670 ssleep(RENDEZVOUS_RETRY_SECS);
673 ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
686 /***************************************************************************************
688 Following this is the implementation of the palacios->host interface
690 **************************************************************************************/
693 /* Attempt to rendezvous with the user device if no device is currently connected */
694 static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
699 if (dev->connected) {
704 INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
706 // Now wait until we are noticed!
707 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
708 spin_lock_irqsave(&(dev->lock),f);
709 if (dev->connected) {
710 INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
711 spin_unlock_irqrestore(&(dev->lock),f);
714 spin_unlock_irqrestore(&(dev->lock),f);
715 ssleep(RENDEZVOUS_RETRY_SECS);
718 ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
720 // We stay in the list because a future rendezvous might happen
726 /* Creates the device without rendezvous */
727 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
730 void *host_priv_data)
732 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
733 struct palacios_host_device_user *dev;
734 struct palacios_host_dev * host_dev = NULL;
738 I will create the device in the list and then wait
739 for the user side to attach
747 host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
749 if (host_dev == NULL) {
750 ERROR("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
755 if (strncasecmp(url,"user:",5)) {
756 ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
760 // Check to see if a device of this url already exists, which would be ugly
761 spin_lock_irqsave(&(host_dev->lock),f);
762 list_for_each_entry(dev,&(host_dev->devs), node) {
763 if (!strncasecmp(url,dev->url,MAX_URL)) {
765 spin_unlock_irqrestore(&(host_dev->lock),f);
766 ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
770 spin_unlock_irqrestore(&(host_dev->lock),f);
773 INFO("palacios: creating host device \"%s\"\n",url);
775 dev = palacios_alloc(sizeof(struct palacios_host_device_user));
778 ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
782 memset(dev,0,sizeof(struct palacios_host_device_user));
784 strncpy(dev->url,url,MAX_URL);
786 dev->guestdev = gdev;
790 spin_lock_init(&(dev->lock));
792 init_waitqueue_head(&(dev->user_wait_queue));
793 init_waitqueue_head(&(dev->host_wait_queue));
795 // Insert ourselves into the list
796 spin_lock_irqsave(&(host_dev->lock),f);
797 list_add(&(dev->node),&(host_dev->devs));
798 spin_unlock_irqrestore(&(host_dev->lock),f);
800 INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
808 static int palacios_host_dev_close(v3_host_dev_t hostdev)
810 unsigned long f1, f2;
812 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
813 struct palacios_host_dev * host_dev = NULL;
815 INFO("palacios: closing host device \"%s\"\n",dev->url);
817 if ((dev == NULL) || (dev->guest == NULL)) {
821 host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
824 if (host_dev == NULL) {
828 spin_lock_irqsave(&(host_dev->lock),f1);
830 spin_lock_irqsave(&(dev->lock),f2);
832 if (dev->connected) {
834 // After this, any user side request will return -EFAULT
837 list_del(&(dev->node));
839 spin_unlock_irqrestore(&(dev->lock),f2);
840 spin_unlock_irqrestore(&(host_dev->lock),f1);
842 palacios_host_dev_user_free(dev);
850 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
855 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
859 DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
862 spin_lock_irqsave(&(dev->lock),f);
864 if (palacios_host_dev_rendezvous(dev)) {
865 spin_unlock_irqrestore(&(dev->lock),f);
866 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
871 spin_unlock_irqrestore(&(dev->lock),f);
872 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);
878 // resize request (no data)
879 if (!palacios_bigenough_reqresp(dev->req,0)) {
881 // we drop the lock, turn on interrupts, resize, and then retry
882 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
884 spin_unlock_irqrestore(&(dev->lock),f);
886 if (palacios_resize_reqresp(&(dev->req),0,0)) {
887 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
890 // reacquire the lock
891 // There shouldn't be a race here since there should not be another
892 // request from palacios until this one finishes
893 spin_lock_irqsave(&(dev->lock),f);
894 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
899 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
901 dev->req->op_len=len;
903 dev->req->conf_addr=0;
904 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
908 spin_unlock_irqrestore(&(dev->lock),f);
910 // hand over to the user space and wait for it to respond
911 cycle_request_response(dev);
913 // We're back! So now we'll hand the response back to Palacios
915 spin_lock_irqsave(&(dev->lock),f);
917 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
919 memcpy(dest,dev->resp->data, op_len);
921 spin_unlock_irqrestore(&(dev->lock),f);
926 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
931 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
935 DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa);
937 spin_lock_irqsave(&(dev->lock),f);
939 if (palacios_host_dev_rendezvous(dev)) {
940 spin_unlock_irqrestore(&(dev->lock),f);
941 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
946 spin_unlock_irqrestore(&(dev->lock),f);
947 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);
951 // resize request (no data)
952 if (!palacios_bigenough_reqresp(dev->req,0)) {
954 // we drop the lock, turn on interrupts, resize, and then retry
955 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
957 spin_unlock_irqrestore(&(dev->lock),f);
959 if (palacios_resize_reqresp(&(dev->req),0,0)) {
960 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
963 // reacquire the lock
964 // There shouldn't be a race here since there should not be another
965 // request from palacios until this one finishes
966 spin_lock_irqsave(&(dev->lock),f);
967 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
971 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
973 dev->req->op_len=len;
975 dev->req->conf_addr=0;
976 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
980 spin_unlock_irqrestore(&(dev->lock),f);
982 // hand over to the user space and wait for it to respond
983 cycle_request_response(dev);
985 // We're back! So now we'll hand the response back to Palacios
987 spin_lock_irqsave(&(dev->lock),f);
989 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
991 memcpy(dest,dev->resp->data, op_len);
993 spin_unlock_irqrestore(&(dev->lock),f);
998 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
1003 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1007 DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
1009 spin_lock_irqsave(&(dev->lock),f);
1011 if (palacios_host_dev_rendezvous(dev)) {
1012 spin_unlock_irqrestore(&(dev->lock),f);
1013 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1018 spin_unlock_irqrestore(&(dev->lock),f);
1019 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);
1023 // resize request (no data)
1024 if (!palacios_bigenough_reqresp(dev->req,0)) {
1026 // we drop the lock, turn on interrupts, resize, and then retry
1027 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1029 spin_unlock_irqrestore(&(dev->lock),f);
1031 if (palacios_resize_reqresp(&(dev->req),0,0)) {
1032 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1035 // reacquire the lock
1036 // There shouldn't be a race here since there should not be another
1037 // request from palacios until this one finishes
1038 spin_lock_irqsave(&(dev->lock),f);
1039 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1043 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1045 dev->req->op_len=len;
1047 dev->req->conf_addr=offset;
1048 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1052 spin_unlock_irqrestore(&(dev->lock),f);
1054 // hand over to the user space and wait for it to respond
1055 cycle_request_response(dev);
1057 // We're back! So now we'll hand the response back to Palacios
1059 spin_lock_irqsave(&(dev->lock),f);
1061 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1063 memcpy(dest,dev->resp->data, op_len);
1065 spin_unlock_irqrestore(&(dev->lock),f);
1071 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1076 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1080 DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1082 spin_lock_irqsave(&(dev->lock),f);
1084 if (palacios_host_dev_rendezvous(dev)) {
1085 spin_unlock_irqrestore(&(dev->lock),f);
1086 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1091 spin_unlock_irqrestore(&(dev->lock),f);
1092 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);
1097 if (!palacios_bigenough_reqresp(dev->req,len)) {
1099 // we drop the lock, turn on interrupts, resize, and then retry
1100 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1102 spin_unlock_irqrestore(&(dev->lock),f);
1104 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1105 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1108 // reacquire the lock
1109 // There shouldn't be a race here since there should not be another
1110 // request from palacios until this one finishes
1111 spin_lock_irqsave(&(dev->lock),f);
1112 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1116 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1117 dev->req->port=port;
1118 dev->req->op_len=len;
1120 dev->req->conf_addr=0;
1121 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1123 memcpy(dev->req->data,src,len);
1127 spin_unlock_irqrestore(&(dev->lock),f);
1129 // hand over to the user space and wait for it to respond
1130 cycle_request_response(dev);
1132 // We're back! So now we'll hand the response back to Palacios
1134 spin_lock_irqsave(&(dev->lock),f);
1136 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1138 spin_unlock_irqrestore(&(dev->lock),f);
1144 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1149 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1153 DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1155 spin_lock_irqsave(&(dev->lock),f);
1157 if (palacios_host_dev_rendezvous(dev)) {
1158 spin_unlock_irqrestore(&(dev->lock),f);
1159 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1164 spin_unlock_irqrestore(&(dev->lock),f);
1165 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);
1170 if (!palacios_bigenough_reqresp(dev->req,len)) {
1172 // we drop the lock, turn on interrupts, resize, and then retry
1173 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1175 spin_unlock_irqrestore(&(dev->lock),f);
1177 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1178 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1181 // reacquire the lock
1182 // There shouldn't be a race here since there should not be another
1183 // request from palacios until this one finishes
1184 spin_lock_irqsave(&(dev->lock),f);
1185 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1189 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1191 dev->req->op_len=len;
1193 dev->req->conf_addr=0;
1194 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1196 memcpy(dev->req->data,src,len);
1200 spin_unlock_irqrestore(&(dev->lock),f);
1202 // hand over to the user space and wait for it to respond
1203 cycle_request_response(dev);
1205 // We're back! So now we'll hand the response back to Palacios
1207 spin_lock_irqsave(&(dev->lock),f);
1209 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1211 spin_unlock_irqrestore(&(dev->lock),f);
1219 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1224 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1228 DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1230 spin_lock_irqsave(&(dev->lock),f);
1232 if (palacios_host_dev_rendezvous(dev)) {
1233 spin_unlock_irqrestore(&(dev->lock),f);
1234 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1239 spin_unlock_irqrestore(&(dev->lock),f);
1240 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);
1245 if (!palacios_bigenough_reqresp(dev->req,len)) {
1247 // we drop the lock, turn on interrupts, resize, and then retry
1248 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1250 spin_unlock_irqrestore(&(dev->lock),f);
1252 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1253 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1256 // reacquire the lock
1257 // There shouldn't be a race here since there should not be another
1258 // request from palacios until this one finishes
1259 spin_lock_irqsave(&(dev->lock),f);
1260 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1264 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1266 dev->req->op_len=len;
1268 dev->req->conf_addr=offset;
1269 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1271 memcpy(dev->req->data,src,len);
1275 spin_unlock_irqrestore(&(dev->lock),f);
1277 // hand over to the user space and wait for it to respond
1278 cycle_request_response(dev);
1280 // We're back! So now we'll hand the response back to Palacios
1282 spin_lock_irqsave(&(dev->lock),f);
1284 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1286 spin_unlock_irqrestore(&(dev->lock),f);
1292 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1302 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1303 .open = palacios_host_dev_open_deferred,
1304 .close = palacios_host_dev_close,
1305 .read_io = palacios_host_dev_read_io,
1306 .write_io = palacios_host_dev_write_io,
1307 .read_mem = palacios_host_dev_read_mem,
1308 .write_mem = palacios_host_dev_write_mem,
1309 .read_config = palacios_host_dev_read_conf,
1310 .write_config = palacios_host_dev_write_conf,
1311 .ack_irq = palacios_host_dev_ack_irq,
1316 static int host_dev_init( void ) {
1317 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1323 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1324 struct palacios_host_dev * host_dev = palacios_alloc(sizeof(struct palacios_host_dev));
1327 ERROR("palacios: failed to do guest_init for host device\n");
1332 INIT_LIST_HEAD(&(host_dev->devs));
1333 spin_lock_init(&(host_dev->lock));
1335 *vm_data = host_dev;
1338 add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
1344 static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) {
1346 palacios_free(vm_data);
1353 static struct linux_ext host_dev_ext = {
1354 .name = "HOST_DEVICE_INTERFACE",
1355 .init = host_dev_init,
1357 .guest_init = host_dev_guest_init,
1358 .guest_deinit = host_dev_guest_deinit
1362 register_extension(&host_dev_ext);