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...) printk((fmt), ##args)
132 #define DEEP_DEBUG_PRINT(fmt, args...)
136 #define SHALLOW_DEBUG_PRINT(fmt, args...) printk((fmt), ##args)
138 #define SHALLOW_DEBUG_PRINT(fmt, args...)
142 #define ERROR(fmt, args...) printk((fmt), ##args)
143 #define INFO(fmt, args...) printk((fmt), ##args)
145 struct palacios_host_device_user {
147 int connected; // is the user space connected to this?
148 int waiting; // am I waiting for a user-space response?
150 int fd; // what is the user space fd?
152 char url[MAX_URL]; // what is the url describing the device
154 v3_guest_dev_t guestdev; // what is the palacios-side device
156 wait_queue_head_t user_wait_queue; // user space processes waiting on us (should be only one)
157 wait_queue_head_t host_wait_queue; // host threads (should only be one) waiting on user space
159 struct v3_guest *guest; // my guest
160 struct palacios_host_dev_host_request_response *req; // curent request
161 struct palacios_host_dev_host_request_response *resp; // curent response
163 struct list_head node; // for adding me to the list of hostdevs this VM has
167 /**************************************************************************************
169 *************************************************************************************/
171 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
186 // Is this structure big enough for the data_size we will use?
188 // THIS FUNCTION CAN BE CALLED WHILE INTERRUPTS ARE OFF
190 static int palacios_bigenough_reqresp(struct palacios_host_dev_host_request_response *r, uint64_t data_size)
195 if (((r->len)-sizeof(struct palacios_host_dev_host_request_response)) < data_size) {
204 // Resize a request/response structure so that it will fit data_size bytes
206 // At the end of this, *r->len >= sizeof(struct)+data_size
208 // THIS FUNCTION MAY SLEEP AS IT CALLS KMALLOC
209 // DO NOT CALL IT WHILE HOLDING A SPIN LOCK WITH INTERRUPTS OFF
211 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
214 DEEP_DEBUG_PRINT("palacios: hostdev: resize 0x%p to %llu\n",*r,data_size);
218 DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n");
219 *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
220 DEEP_DEBUG_PRINT("palacios: hostdev: kmalloc done\n");
222 ERROR("palacios: hostdev: failed to allocate\n");
225 (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
226 DEEP_DEBUG_PRINT("palacios: hostdev: allocated\n");
230 //let it go if it's big enough
231 uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
233 if (data_size<=cur_len) {
235 DEEP_DEBUG_PRINT("palacios: hostdev: size ok\n");
238 struct palacios_host_dev_host_request_response *new;
244 new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
246 ERROR("palacios: hostdev: failed to reallocate\n");
249 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
251 memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
252 new->data_len=(*r)->data_len;
256 DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n");
263 static void cycle_request_response(struct palacios_host_device_user *dev)
265 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response\n");
266 // wake up user side so that polls fall through
267 wake_up_interruptible(&(dev->user_wait_queue));
268 // put us to sleep until the user side wakes us up
269 while (wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0)) != 0) {}
271 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response - done\n");
274 static void cycle_response_request(struct palacios_host_device_user *dev)
276 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request\n");
278 wake_up_interruptible(&(dev->host_wait_queue));
279 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request - done\n");
283 /*********************************************************************************************
285 Interface to user space
287 *********************************************************************************************/
291 static unsigned int host_dev_poll(struct file * filp,
292 struct poll_table_struct * poll_tb)
295 struct palacios_host_device_user * dev = filp->private_data;
298 SHALLOW_DEBUG_PRINT("palacios: hostdev: poll\n");
300 if (!dev->connected) {
301 ERROR("palcios: hostdev: poll on unconnected device\n");
305 spin_lock_irqsave(&(dev->lock),f);
308 // Yes, we have a request if you want it!
309 spin_unlock_irqrestore(&(dev->lock),f);
310 DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n");
311 return POLLIN | POLLRDNORM;
314 // No request yet, so we need to wait for one to show up.
316 // register ourselves on the user wait queue
317 poll_wait(filp, &(dev->user_wait_queue), poll_tb);
319 spin_unlock_irqrestore(&(dev->lock),f);
321 DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
322 // We will get called again when that queue is woken up
328 static int host_dev_release(struct inode * i, struct file * filp)
330 struct palacios_host_device_user *dev = filp->private_data;
333 INFO("palacios: user side is closing host device \"%s\"\n",dev->url);
335 spin_lock_irqsave(&(dev->lock), f);
337 spin_unlock_irqrestore(&(dev->lock), f);
339 // it is the palacios->host interface's responsibility to ignore
340 // reads/writes until connected is true
345 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
347 void __user *argp = (void __user *)arg;
349 struct palacios_host_device_user *dev = fp->private_data;
351 DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
354 if (!dev->connected) {
355 ERROR("palacios: hostdev: ioctl on unconnected device\n");
360 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
362 struct palacios_host_dev_user_op op;
364 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
365 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
369 DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
372 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
373 void *temp = kmalloc(op.len,GFP_KERNEL);
375 DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
378 ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
382 if (v3_host_dev_read_guest_mem(dev->guestdev,
387 ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
392 if (copy_to_user(op.data,temp,op.len)) {
393 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
405 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
408 DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
410 temp = kmalloc(op.len,GFP_KERNEL);
413 ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
417 if (copy_from_user(temp,op.data,op.len)) {
418 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
423 if (v3_host_dev_write_guest_mem(dev->guestdev,
428 ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
439 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
441 DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
443 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
448 ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
455 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
460 DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
462 spin_lock_irqsave(&(dev->lock),f);
464 if (!(dev->waiting)) {
465 spin_unlock_irqrestore(&(dev->lock),f);
466 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
467 schedule(); // avoid livelock for polling user space process SUSPICOUS
468 return 0; // no request available now
471 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
472 spin_unlock_irqrestore(&(dev->lock),f);
473 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
474 return -EFAULT; // failed to copy!
478 spin_unlock_irqrestore(&(dev->lock),f);
480 DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
482 return 1; // have request for you
488 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
492 spin_lock_irqsave(&(dev->lock),f);
494 DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
496 if (!(dev->waiting) || !(dev->req)) {
497 spin_unlock_irqrestore(&(dev->lock),f);
498 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
499 return 0; // no request available now
503 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
504 spin_unlock_irqrestore(&(dev->lock),f);
505 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
506 return -EFAULT; // failed to copy!
509 spin_unlock_irqrestore(&(dev->lock),f);
511 DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
513 return 1; // copied request for you
517 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
520 uint64_t user_datalen;
523 spin_lock_irqsave(&(dev->lock),f);
525 DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
527 if (!(dev->waiting)) {
528 spin_unlock_irqrestore(&(dev->lock),f);
529 ERROR("palacios: hostdev: no matching request for pushed response\n");
530 return 0; // no request outstanding, so we do not need a response!
533 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
534 spin_unlock_irqrestore(&(dev->lock),f);
535 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
536 return -EFAULT; // failed to copy!
539 if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) {
541 spin_unlock_irqrestore(&(dev->lock),f);
542 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
546 if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
548 // we drop the lock, turn on interrupts, resize, and then retry
549 DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
551 spin_unlock_irqrestore(&(dev->lock),f);
553 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
554 ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
557 // reacquire the lock
558 // There shouldn't be a race here, since there should
559 // be exactly one user space thread giving us a response for this device
560 // and it is blocked waiting for us to finish
561 spin_lock_irqsave(&(dev->lock),f);
562 DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
566 //We only copy data_len bytes from user, but we will
567 //overwrite the len field, so we preserve and then restore
568 old_len = dev->resp->len;
569 if (copy_from_user(dev->resp, argp, user_datalen)) {
570 dev->resp->len=old_len;
571 spin_unlock_irqrestore(&(dev->lock),f);
572 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
573 return -EFAULT; // failed to copy!
575 dev->resp->len=old_len;
577 DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
578 // now have valid response!
581 spin_unlock_irqrestore(&(dev->lock),f);
583 // wake the palacios side up so that it sees it
584 cycle_response_request(dev);
591 ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
598 static long host_dev_compat_ioctl(struct file * filp, unsigned int ioctl, unsigned long arg)
600 return host_dev_ioctl(NULL, filp, ioctl, arg);
603 static struct file_operations host_dev_fops = {
604 .poll = host_dev_poll,
605 .release = host_dev_release,
606 #ifdef HAVE_COMPAT_IOCTL
607 .compat_ioctl = host_dev_compat_ioctl,
609 .ioctl = host_dev_ioctl,
615 static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data)
617 void __user * argp = (void __user *)arg;
619 struct palacios_host_dev * host_dev = priv_data;
620 struct palacios_host_device_user *dev;
621 unsigned long f1, f2;
626 if (copy_from_user(url, argp, MAX_URL)) {
627 printk("copy from user error getting url for host device connect...\n");
631 // currently only support user: types:
632 if (strncasecmp(url,"user:",5)) {
633 ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
637 INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
639 // We will scan the list looking for the relevant
640 // URL. If we don't find it after a while, we give up
642 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
643 spin_lock_irqsave(&(host_dev->lock),f1);
644 list_for_each_entry(dev,&(host_dev->devs), node) {
645 if (!strncasecmp(url,dev->url,MAX_URL)) {
647 spin_lock_irqsave(&(dev->lock),f2);
648 if (dev->connected) {
649 ERROR("palacios: device for \"%s\" is already connected!\n",url);
650 spin_unlock_irqrestore(&(dev->lock),f2);
651 spin_unlock_irqrestore(&(host_dev->lock),f1);
654 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
656 ERROR("palacios: cannot create fd for device \"%s\"\n",url);
657 spin_unlock_irqrestore(&(dev->lock),f2);
658 spin_unlock_irqrestore(&(host_dev->lock),f1);
671 INFO("palacios: connected fd for device \"%s\"\n",url);
672 spin_unlock_irqrestore(&(dev->lock),f2);
673 spin_unlock_irqrestore(&(host_dev->lock),f1);
676 spin_unlock_irqrestore(&(dev->lock),f2);
679 spin_unlock_irqrestore(&(host_dev->lock),f1);
681 ssleep(RENDEZVOUS_RETRY_SECS);
684 ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
697 /***************************************************************************************
699 Following this is the implementation of the palacios->host interface
701 **************************************************************************************/
704 /* Attempt to rendezvous with the user device if no device is currently connected */
705 static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
710 if (dev->connected) {
715 INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
717 // Now wait until we are noticed!
718 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
719 spin_lock_irqsave(&(dev->lock),f);
720 if (dev->connected) {
721 INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
722 spin_unlock_irqrestore(&(dev->lock),f);
725 spin_unlock_irqrestore(&(dev->lock),f);
726 ssleep(RENDEZVOUS_RETRY_SECS);
729 ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
731 // We stay in the list because a future rendezvous might happen
737 /* Creates the device without rendezvous */
738 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
741 void *host_priv_data)
743 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
744 struct palacios_host_device_user *dev;
745 struct palacios_host_dev * host_dev = NULL;
749 I will create the device in the list and then wait
750 for the user side to attach
758 host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
760 if (host_dev == NULL) {
761 printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
766 if (strncasecmp(url,"user:",5)) {
767 ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
771 // Check to see if a device of this url already exists, which would be ugly
772 spin_lock_irqsave(&(host_dev->lock),f);
773 list_for_each_entry(dev,&(host_dev->devs), node) {
774 if (!strncasecmp(url,dev->url,MAX_URL)) {
776 spin_unlock_irqrestore(&(host_dev->lock),f);
777 ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
781 spin_unlock_irqrestore(&(host_dev->lock),f);
784 INFO("palacios: creating host device \"%s\"\n",url);
786 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
789 ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
793 memset(dev,0,sizeof(struct palacios_host_device_user));
795 strncpy(dev->url,url,MAX_URL);
797 dev->guestdev = gdev;
801 spin_lock_init(&(dev->lock));
803 init_waitqueue_head(&(dev->user_wait_queue));
804 init_waitqueue_head(&(dev->host_wait_queue));
806 // Insert ourselves into the list
807 spin_lock_irqsave(&(host_dev->lock),f);
808 list_add(&(dev->node),&(host_dev->devs));
809 spin_unlock_irqrestore(&(host_dev->lock),f);
811 INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
819 static int palacios_host_dev_close(v3_host_dev_t hostdev)
821 unsigned long f1, f2;
823 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
824 struct palacios_host_dev * host_dev = NULL;
826 INFO("palacios: closing host device \"%s\"\n",dev->url);
828 if ((dev == NULL) || (dev->guest == NULL)) {
832 host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
835 if (host_dev == NULL) {
839 spin_lock_irqsave(&(host_dev->lock),f1);
841 spin_lock_irqsave(&(dev->lock),f2);
843 if (dev->connected) {
845 // After this, any user side request will return -EFAULT
848 list_del(&(dev->node));
850 spin_unlock_irqrestore(&(dev->lock),f2);
851 spin_unlock_irqrestore(&(host_dev->lock),f1);
853 palacios_host_dev_user_free(dev);
861 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
866 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
870 DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
873 spin_lock_irqsave(&(dev->lock),f);
875 if (palacios_host_dev_rendezvous(dev)) {
876 spin_unlock_irqrestore(&(dev->lock),f);
877 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
882 spin_unlock_irqrestore(&(dev->lock),f);
883 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);
889 // resize request (no data)
890 if (!palacios_bigenough_reqresp(dev->req,0)) {
892 // we drop the lock, turn on interrupts, resize, and then retry
893 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
895 spin_unlock_irqrestore(&(dev->lock),f);
897 if (palacios_resize_reqresp(&(dev->req),0,0)) {
898 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
901 // reacquire the lock
902 // There shouldn't be a race here since there should not be another
903 // request from palacios until this one finishes
904 spin_lock_irqsave(&(dev->lock),f);
905 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
910 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
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);
919 spin_unlock_irqrestore(&(dev->lock),f);
921 // hand over to the user space and wait for it to respond
922 cycle_request_response(dev);
924 // We're back! So now we'll hand the response back to Palacios
926 spin_lock_irqsave(&(dev->lock),f);
928 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
930 memcpy(dest,dev->resp->data, op_len);
932 spin_unlock_irqrestore(&(dev->lock),f);
937 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
942 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
946 DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa);
948 spin_lock_irqsave(&(dev->lock),f);
950 if (palacios_host_dev_rendezvous(dev)) {
951 spin_unlock_irqrestore(&(dev->lock),f);
952 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
957 spin_unlock_irqrestore(&(dev->lock),f);
958 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);
962 // resize request (no data)
963 if (!palacios_bigenough_reqresp(dev->req,0)) {
965 // we drop the lock, turn on interrupts, resize, and then retry
966 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
968 spin_unlock_irqrestore(&(dev->lock),f);
970 if (palacios_resize_reqresp(&(dev->req),0,0)) {
971 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
974 // reacquire the lock
975 // There shouldn't be a race here since there should not be another
976 // request from palacios until this one finishes
977 spin_lock_irqsave(&(dev->lock),f);
978 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
982 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
984 dev->req->op_len=len;
986 dev->req->conf_addr=0;
987 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
991 spin_unlock_irqrestore(&(dev->lock),f);
993 // hand over to the user space and wait for it to respond
994 cycle_request_response(dev);
996 // We're back! So now we'll hand the response back to Palacios
998 spin_lock_irqsave(&(dev->lock),f);
1000 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1002 memcpy(dest,dev->resp->data, op_len);
1004 spin_unlock_irqrestore(&(dev->lock),f);
1009 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
1014 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1018 DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
1020 spin_lock_irqsave(&(dev->lock),f);
1022 if (palacios_host_dev_rendezvous(dev)) {
1023 spin_unlock_irqrestore(&(dev->lock),f);
1024 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1029 spin_unlock_irqrestore(&(dev->lock),f);
1030 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);
1034 // resize request (no data)
1035 if (!palacios_bigenough_reqresp(dev->req,0)) {
1037 // we drop the lock, turn on interrupts, resize, and then retry
1038 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1040 spin_unlock_irqrestore(&(dev->lock),f);
1042 if (palacios_resize_reqresp(&(dev->req),0,0)) {
1043 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1046 // reacquire the lock
1047 // There shouldn't be a race here since there should not be another
1048 // request from palacios until this one finishes
1049 spin_lock_irqsave(&(dev->lock),f);
1050 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1054 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1056 dev->req->op_len=len;
1058 dev->req->conf_addr=offset;
1059 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1063 spin_unlock_irqrestore(&(dev->lock),f);
1065 // hand over to the user space and wait for it to respond
1066 cycle_request_response(dev);
1068 // We're back! So now we'll hand the response back to Palacios
1070 spin_lock_irqsave(&(dev->lock),f);
1072 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1074 memcpy(dest,dev->resp->data, op_len);
1076 spin_unlock_irqrestore(&(dev->lock),f);
1082 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1087 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1091 DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1093 spin_lock_irqsave(&(dev->lock),f);
1095 if (palacios_host_dev_rendezvous(dev)) {
1096 spin_unlock_irqrestore(&(dev->lock),f);
1097 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1102 spin_unlock_irqrestore(&(dev->lock),f);
1103 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);
1108 if (!palacios_bigenough_reqresp(dev->req,len)) {
1110 // we drop the lock, turn on interrupts, resize, and then retry
1111 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1113 spin_unlock_irqrestore(&(dev->lock),f);
1115 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1116 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1119 // reacquire the lock
1120 // There shouldn't be a race here since there should not be another
1121 // request from palacios until this one finishes
1122 spin_lock_irqsave(&(dev->lock),f);
1123 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1127 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1128 dev->req->port=port;
1129 dev->req->op_len=len;
1131 dev->req->conf_addr=0;
1132 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1134 memcpy(dev->req->data,src,len);
1138 spin_unlock_irqrestore(&(dev->lock),f);
1140 // hand over to the user space and wait for it to respond
1141 cycle_request_response(dev);
1143 // We're back! So now we'll hand the response back to Palacios
1145 spin_lock_irqsave(&(dev->lock),f);
1147 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1149 spin_unlock_irqrestore(&(dev->lock),f);
1155 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1160 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1164 DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1166 spin_lock_irqsave(&(dev->lock),f);
1168 if (palacios_host_dev_rendezvous(dev)) {
1169 spin_unlock_irqrestore(&(dev->lock),f);
1170 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1175 spin_unlock_irqrestore(&(dev->lock),f);
1176 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);
1181 if (!palacios_bigenough_reqresp(dev->req,len)) {
1183 // we drop the lock, turn on interrupts, resize, and then retry
1184 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1186 spin_unlock_irqrestore(&(dev->lock),f);
1188 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1189 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1192 // reacquire the lock
1193 // There shouldn't be a race here since there should not be another
1194 // request from palacios until this one finishes
1195 spin_lock_irqsave(&(dev->lock),f);
1196 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1200 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1202 dev->req->op_len=len;
1204 dev->req->conf_addr=0;
1205 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1207 memcpy(dev->req->data,src,len);
1211 spin_unlock_irqrestore(&(dev->lock),f);
1213 // hand over to the user space and wait for it to respond
1214 cycle_request_response(dev);
1216 // We're back! So now we'll hand the response back to Palacios
1218 spin_lock_irqsave(&(dev->lock),f);
1220 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1222 spin_unlock_irqrestore(&(dev->lock),f);
1230 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1235 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1239 DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1241 spin_lock_irqsave(&(dev->lock),f);
1243 if (palacios_host_dev_rendezvous(dev)) {
1244 spin_unlock_irqrestore(&(dev->lock),f);
1245 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1250 spin_unlock_irqrestore(&(dev->lock),f);
1251 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);
1256 if (!palacios_bigenough_reqresp(dev->req,len)) {
1258 // we drop the lock, turn on interrupts, resize, and then retry
1259 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1261 spin_unlock_irqrestore(&(dev->lock),f);
1263 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1264 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1267 // reacquire the lock
1268 // There shouldn't be a race here since there should not be another
1269 // request from palacios until this one finishes
1270 spin_lock_irqsave(&(dev->lock),f);
1271 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1275 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1277 dev->req->op_len=len;
1279 dev->req->conf_addr=offset;
1280 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1282 memcpy(dev->req->data,src,len);
1286 spin_unlock_irqrestore(&(dev->lock),f);
1288 // hand over to the user space and wait for it to respond
1289 cycle_request_response(dev);
1291 // We're back! So now we'll hand the response back to Palacios
1293 spin_lock_irqsave(&(dev->lock),f);
1295 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1297 spin_unlock_irqrestore(&(dev->lock),f);
1303 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1313 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1314 .open = palacios_host_dev_open_deferred,
1315 .close = palacios_host_dev_close,
1316 .read_io = palacios_host_dev_read_io,
1317 .write_io = palacios_host_dev_write_io,
1318 .read_mem = palacios_host_dev_read_mem,
1319 .write_mem = palacios_host_dev_write_mem,
1320 .read_config = palacios_host_dev_read_conf,
1321 .write_config = palacios_host_dev_write_conf,
1322 .ack_irq = palacios_host_dev_ack_irq,
1327 static int host_dev_init( void ) {
1328 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1334 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1335 struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL);
1338 ERROR("palacios: failed to do guest_init for host device\n");
1343 INIT_LIST_HEAD(&(host_dev->devs));
1344 spin_lock_init(&(host_dev->lock));
1346 *vm_data = host_dev;
1349 add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
1358 static struct linux_ext host_dev_ext = {
1359 .name = "HOST_DEVICE_INTERFACE",
1360 .init = host_dev_init,
1362 .guest_init = host_dev_guest_init,
1363 .guest_deinit = NULL
1367 register_extension(&host_dev_ext);