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
346 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
348 void __user *argp = (void __user *)arg;
350 struct palacios_host_device_user *dev = fp->private_data;
352 DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
355 if (!dev->connected) {
356 ERROR("palacios: hostdev: ioctl on unconnected device\n");
361 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
363 struct palacios_host_dev_user_op op;
365 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
366 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
370 DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
373 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
374 void *temp = kmalloc(op.len,GFP_KERNEL);
376 DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
379 ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
383 if (v3_host_dev_read_guest_mem(dev->guestdev,
388 ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
393 if (copy_to_user(op.data,temp,op.len)) {
394 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
406 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
409 DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
411 temp = kmalloc(op.len,GFP_KERNEL);
414 ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
418 if (copy_from_user(temp,op.data,op.len)) {
419 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
424 if (v3_host_dev_write_guest_mem(dev->guestdev,
429 ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
440 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
442 DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
444 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
449 ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
456 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
461 DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
463 spin_lock_irqsave(&(dev->lock),f);
465 if (!(dev->waiting)) {
466 spin_unlock_irqrestore(&(dev->lock),f);
467 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
468 schedule(); // avoid livelock for polling user space process SUSPICOUS
469 return 0; // no request available now
472 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
473 spin_unlock_irqrestore(&(dev->lock),f);
474 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
475 return -EFAULT; // failed to copy!
479 spin_unlock_irqrestore(&(dev->lock),f);
481 DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
483 return 1; // have request for you
489 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
493 spin_lock_irqsave(&(dev->lock),f);
495 DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
497 if (!(dev->waiting) || !(dev->req)) {
498 spin_unlock_irqrestore(&(dev->lock),f);
499 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
500 return 0; // no request available now
504 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
505 spin_unlock_irqrestore(&(dev->lock),f);
506 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
507 return -EFAULT; // failed to copy!
510 spin_unlock_irqrestore(&(dev->lock),f);
512 DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
514 return 1; // copied request for you
518 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
521 uint64_t user_datalen;
524 spin_lock_irqsave(&(dev->lock),f);
526 DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
528 if (!(dev->waiting)) {
529 spin_unlock_irqrestore(&(dev->lock),f);
530 ERROR("palacios: hostdev: no matching request for pushed response\n");
531 return 0; // no request outstanding, so we do not need a response!
534 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
535 spin_unlock_irqrestore(&(dev->lock),f);
536 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
537 return -EFAULT; // failed to copy!
540 if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) {
542 spin_unlock_irqrestore(&(dev->lock),f);
543 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
547 if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
549 // we drop the lock, turn on interrupts, resize, and then retry
550 DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
552 spin_unlock_irqrestore(&(dev->lock),f);
554 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
555 ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
558 // reacquire the lock
559 // There shouldn't be a race here, since there should
560 // be exactly one user space thread giving us a response for this device
561 // and it is blocked waiting for us to finish
562 spin_lock_irqsave(&(dev->lock),f);
563 DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
567 //We only copy data_len bytes from user, but we will
568 //overwrite the len field, so we preserve and then restore
569 old_len = dev->resp->len;
570 if (copy_from_user(dev->resp, argp, user_datalen)) {
571 dev->resp->len=old_len;
572 spin_unlock_irqrestore(&(dev->lock),f);
573 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
574 return -EFAULT; // failed to copy!
576 dev->resp->len=old_len;
578 DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
579 // now have valid response!
582 spin_unlock_irqrestore(&(dev->lock),f);
584 // wake the palacios side up so that it sees it
585 cycle_response_request(dev);
592 ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
602 static struct file_operations host_dev_fops = {
603 .poll = host_dev_poll,
604 .release = host_dev_release,
605 .ioctl = host_dev_ioctl,
610 static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data)
612 void __user * argp = (void __user *)arg;
614 struct palacios_host_dev * host_dev = priv_data;
615 struct palacios_host_device_user *dev;
616 unsigned long f1, f2;
621 if (copy_from_user(url, argp, MAX_URL)) {
622 printk("copy from user error getting url for host device connect...\n");
626 // currently only support user: types:
627 if (strncasecmp(url,"user:",5)) {
628 ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
632 INFO("palacios: attempting to rendezvous with palacios side of host device \"%s\"\n",url);
634 // We will scan the list looking for the relevant
635 // URL. If we don't find it after a while, we give up
637 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
638 spin_lock_irqsave(&(host_dev->lock),f1);
639 list_for_each_entry(dev,&(host_dev->devs), node) {
640 if (!strncasecmp(url,dev->url,MAX_URL)) {
642 spin_lock_irqsave(&(dev->lock),f2);
643 if (dev->connected) {
644 ERROR("palacios: device for \"%s\" is already connected!\n",url);
645 spin_unlock_irqrestore(&(dev->lock),f2);
646 spin_unlock_irqrestore(&(host_dev->lock),f1);
649 dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
651 ERROR("palacios: cannot create fd for device \"%s\"\n",url);
652 spin_unlock_irqrestore(&(dev->lock),f2);
653 spin_unlock_irqrestore(&(host_dev->lock),f1);
666 INFO("palacios: connected fd for device \"%s\"\n",url);
667 spin_unlock_irqrestore(&(dev->lock),f2);
668 spin_unlock_irqrestore(&(host_dev->lock),f1);
671 spin_unlock_irqrestore(&(dev->lock),f2);
674 spin_unlock_irqrestore(&(host_dev->lock),f1);
676 ssleep(RENDEZVOUS_RETRY_SECS);
679 ERROR("palacios: timeout waiting for connection for device \"%s\"",url);
692 /***************************************************************************************
694 Following this is the implementation of the palacios->host interface
696 **************************************************************************************/
699 /* Attempt to rendezvous with the user device if no device is currently connected */
700 static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
705 if (dev->connected) {
710 INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
712 // Now wait until we are noticed!
713 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
714 spin_lock_irqsave(&(dev->lock),f);
715 if (dev->connected) {
716 INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
717 spin_unlock_irqrestore(&(dev->lock),f);
720 spin_unlock_irqrestore(&(dev->lock),f);
721 ssleep(RENDEZVOUS_RETRY_SECS);
724 ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
726 // We stay in the list because a future rendezvous might happen
732 /* Creates the device without rendezvous */
733 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
736 void *host_priv_data)
738 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
739 struct palacios_host_device_user *dev;
740 struct palacios_host_dev * host_dev = NULL;
744 I will create the device in the list and then wait
745 for the user side to attach
753 host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
755 if (host_dev == NULL) {
756 printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
761 if (strncasecmp(url,"user:",5)) {
762 ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
766 // Check to see if a device of this url already exists, which would be ugly
767 spin_lock_irqsave(&(host_dev->lock),f);
768 list_for_each_entry(dev,&(host_dev->devs), node) {
769 if (!strncasecmp(url,dev->url,MAX_URL)) {
771 spin_unlock_irqrestore(&(host_dev->lock),f);
772 ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
776 spin_unlock_irqrestore(&(host_dev->lock),f);
779 INFO("palacios: creating host device \"%s\"\n",url);
781 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
784 ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
788 memset(dev,0,sizeof(struct palacios_host_device_user));
790 strncpy(dev->url,url,MAX_URL);
792 dev->guestdev = gdev;
796 spin_lock_init(&(dev->lock));
798 init_waitqueue_head(&(dev->user_wait_queue));
799 init_waitqueue_head(&(dev->host_wait_queue));
801 // Insert ourselves into the list
802 spin_lock_irqsave(&(host_dev->lock),f);
803 list_add(&(dev->node),&(host_dev->devs));
804 spin_unlock_irqrestore(&(host_dev->lock),f);
806 INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
814 static int palacios_host_dev_close(v3_host_dev_t hostdev)
816 unsigned long f1, f2;
818 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
819 struct palacios_host_dev * host_dev = NULL;
821 INFO("palacios: closing host device \"%s\"\n",dev->url);
823 if ((dev == NULL) || (dev->guest == NULL)) {
827 host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
830 if (host_dev == NULL) {
834 spin_lock_irqsave(&(host_dev->lock),f1);
836 spin_lock_irqsave(&(dev->lock),f2);
838 if (dev->connected) {
840 // After this, any user side request will return -EFAULT
843 list_del(&(dev->node));
845 spin_unlock_irqrestore(&(dev->lock),f2);
846 spin_unlock_irqrestore(&(host_dev->lock),f1);
848 palacios_host_dev_user_free(dev);
856 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
861 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
865 DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
868 spin_lock_irqsave(&(dev->lock),f);
870 if (palacios_host_dev_rendezvous(dev)) {
871 spin_unlock_irqrestore(&(dev->lock),f);
872 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
877 spin_unlock_irqrestore(&(dev->lock),f);
878 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);
884 // resize request (no data)
885 if (!palacios_bigenough_reqresp(dev->req,0)) {
887 // we drop the lock, turn on interrupts, resize, and then retry
888 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
890 spin_unlock_irqrestore(&(dev->lock),f);
892 if (palacios_resize_reqresp(&(dev->req),0,0)) {
893 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
896 // reacquire the lock
897 // There shouldn't be a race here since there should not be another
898 // request from palacios until this one finishes
899 spin_lock_irqsave(&(dev->lock),f);
900 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
905 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
907 dev->req->op_len=len;
909 dev->req->conf_addr=0;
910 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
914 spin_unlock_irqrestore(&(dev->lock),f);
916 // hand over to the user space and wait for it to respond
917 cycle_request_response(dev);
919 // We're back! So now we'll hand the response back to Palacios
921 spin_lock_irqsave(&(dev->lock),f);
923 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
925 memcpy(dest,dev->resp->data, op_len);
927 spin_unlock_irqrestore(&(dev->lock),f);
932 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
937 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
941 DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa);
943 spin_lock_irqsave(&(dev->lock),f);
945 if (palacios_host_dev_rendezvous(dev)) {
946 spin_unlock_irqrestore(&(dev->lock),f);
947 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
952 spin_unlock_irqrestore(&(dev->lock),f);
953 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);
957 // resize request (no data)
958 if (!palacios_bigenough_reqresp(dev->req,0)) {
960 // we drop the lock, turn on interrupts, resize, and then retry
961 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
963 spin_unlock_irqrestore(&(dev->lock),f);
965 if (palacios_resize_reqresp(&(dev->req),0,0)) {
966 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
969 // reacquire the lock
970 // There shouldn't be a race here since there should not be another
971 // request from palacios until this one finishes
972 spin_lock_irqsave(&(dev->lock),f);
973 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
977 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
979 dev->req->op_len=len;
981 dev->req->conf_addr=0;
982 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
986 spin_unlock_irqrestore(&(dev->lock),f);
988 // hand over to the user space and wait for it to respond
989 cycle_request_response(dev);
991 // We're back! So now we'll hand the response back to Palacios
993 spin_lock_irqsave(&(dev->lock),f);
995 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
997 memcpy(dest,dev->resp->data, op_len);
999 spin_unlock_irqrestore(&(dev->lock),f);
1004 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
1009 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1013 DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
1015 spin_lock_irqsave(&(dev->lock),f);
1017 if (palacios_host_dev_rendezvous(dev)) {
1018 spin_unlock_irqrestore(&(dev->lock),f);
1019 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1024 spin_unlock_irqrestore(&(dev->lock),f);
1025 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);
1029 // resize request (no data)
1030 if (!palacios_bigenough_reqresp(dev->req,0)) {
1032 // we drop the lock, turn on interrupts, resize, and then retry
1033 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1035 spin_unlock_irqrestore(&(dev->lock),f);
1037 if (palacios_resize_reqresp(&(dev->req),0,0)) {
1038 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1041 // reacquire the lock
1042 // There shouldn't be a race here since there should not be another
1043 // request from palacios until this one finishes
1044 spin_lock_irqsave(&(dev->lock),f);
1045 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1049 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1051 dev->req->op_len=len;
1053 dev->req->conf_addr=offset;
1054 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1058 spin_unlock_irqrestore(&(dev->lock),f);
1060 // hand over to the user space and wait for it to respond
1061 cycle_request_response(dev);
1063 // We're back! So now we'll hand the response back to Palacios
1065 spin_lock_irqsave(&(dev->lock),f);
1067 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1069 memcpy(dest,dev->resp->data, op_len);
1071 spin_unlock_irqrestore(&(dev->lock),f);
1077 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1082 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1086 DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1088 spin_lock_irqsave(&(dev->lock),f);
1090 if (palacios_host_dev_rendezvous(dev)) {
1091 spin_unlock_irqrestore(&(dev->lock),f);
1092 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1097 spin_unlock_irqrestore(&(dev->lock),f);
1098 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);
1103 if (!palacios_bigenough_reqresp(dev->req,len)) {
1105 // we drop the lock, turn on interrupts, resize, and then retry
1106 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1108 spin_unlock_irqrestore(&(dev->lock),f);
1110 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1111 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1114 // reacquire the lock
1115 // There shouldn't be a race here since there should not be another
1116 // request from palacios until this one finishes
1117 spin_lock_irqsave(&(dev->lock),f);
1118 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1122 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1123 dev->req->port=port;
1124 dev->req->op_len=len;
1126 dev->req->conf_addr=0;
1127 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1129 memcpy(dev->req->data,src,len);
1133 spin_unlock_irqrestore(&(dev->lock),f);
1135 // hand over to the user space and wait for it to respond
1136 cycle_request_response(dev);
1138 // We're back! So now we'll hand the response back to Palacios
1140 spin_lock_irqsave(&(dev->lock),f);
1142 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1144 spin_unlock_irqrestore(&(dev->lock),f);
1150 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1155 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1159 DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1161 spin_lock_irqsave(&(dev->lock),f);
1163 if (palacios_host_dev_rendezvous(dev)) {
1164 spin_unlock_irqrestore(&(dev->lock),f);
1165 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1170 spin_unlock_irqrestore(&(dev->lock),f);
1171 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);
1176 if (!palacios_bigenough_reqresp(dev->req,len)) {
1178 // we drop the lock, turn on interrupts, resize, and then retry
1179 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1181 spin_unlock_irqrestore(&(dev->lock),f);
1183 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1184 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1187 // reacquire the lock
1188 // There shouldn't be a race here since there should not be another
1189 // request from palacios until this one finishes
1190 spin_lock_irqsave(&(dev->lock),f);
1191 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1195 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1197 dev->req->op_len=len;
1199 dev->req->conf_addr=0;
1200 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1202 memcpy(dev->req->data,src,len);
1206 spin_unlock_irqrestore(&(dev->lock),f);
1208 // hand over to the user space and wait for it to respond
1209 cycle_request_response(dev);
1211 // We're back! So now we'll hand the response back to Palacios
1213 spin_lock_irqsave(&(dev->lock),f);
1215 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1217 spin_unlock_irqrestore(&(dev->lock),f);
1225 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1230 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1234 DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1236 spin_lock_irqsave(&(dev->lock),f);
1238 if (palacios_host_dev_rendezvous(dev)) {
1239 spin_unlock_irqrestore(&(dev->lock),f);
1240 ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url);
1245 spin_unlock_irqrestore(&(dev->lock),f);
1246 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);
1251 if (!palacios_bigenough_reqresp(dev->req,len)) {
1253 // we drop the lock, turn on interrupts, resize, and then retry
1254 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1256 spin_unlock_irqrestore(&(dev->lock),f);
1258 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1259 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1262 // reacquire the lock
1263 // There shouldn't be a race here since there should not be another
1264 // request from palacios until this one finishes
1265 spin_lock_irqsave(&(dev->lock),f);
1266 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1270 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1272 dev->req->op_len=len;
1274 dev->req->conf_addr=offset;
1275 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1277 memcpy(dev->req->data,src,len);
1281 spin_unlock_irqrestore(&(dev->lock),f);
1283 // hand over to the user space and wait for it to respond
1284 cycle_request_response(dev);
1286 // We're back! So now we'll hand the response back to Palacios
1288 spin_lock_irqsave(&(dev->lock),f);
1290 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1292 spin_unlock_irqrestore(&(dev->lock),f);
1298 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1308 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1309 .open = palacios_host_dev_open_deferred,
1310 .close = palacios_host_dev_close,
1311 .read_io = palacios_host_dev_read_io,
1312 .write_io = palacios_host_dev_write_io,
1313 .read_mem = palacios_host_dev_read_mem,
1314 .write_mem = palacios_host_dev_write_mem,
1315 .read_config = palacios_host_dev_read_conf,
1316 .write_config = palacios_host_dev_write_conf,
1317 .ack_irq = palacios_host_dev_ack_irq,
1322 static int host_dev_init( void ) {
1323 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1329 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1330 struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL);
1333 ERROR("palacios: failed to do guest_init for host device\n");
1338 INIT_LIST_HEAD(&(host_dev->devs));
1339 spin_lock_init(&(host_dev->lock));
1341 *vm_data = host_dev;
1344 add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
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 = NULL
1362 register_extension(&host_dev_ext);