2 * Host device interface + user-space device interface
6 #include <linux/device.h>
7 #include <linux/cdev.h>
8 #include <linux/errno.h>
10 #include <linux/uaccess.h>
11 #include <linux/poll.h>
12 #include <linux/anon_inodes.h>
13 #include <linux/file.h>
14 #include <linux/sched.h>
15 #include <linux/delay.h>
17 #include <interfaces/vmm_host_dev.h>
20 #include "palacios-host-dev-user.h"
21 #include "linux-exts.h"
22 #include "palacios-vm.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
109 struct palacios_host_dev {
111 struct list_head devs;
117 #define RENDEZVOUS_WAIT_SECS 60
118 #define RENDEZVOUS_RETRY_SECS 1
121 #define SHALLOW_DEBUG 0
124 #define DEEP_DEBUG_PRINT(fmt, args...) printk((fmt), ##args)
126 #define DEEP_DEBUG_PRINT(fmt, args...)
130 #define SHALLOW_DEBUG_PRINT(fmt, args...) printk((fmt), ##args)
132 #define SHALLOW_DEBUG_PRINT(fmt, args...)
136 #define ERROR(fmt, args...) printk((fmt), ##args)
137 #define INFO(fmt, args...) printk((fmt), ##args)
139 struct palacios_host_device_user {
141 int connected; // is the user space connected to this?
142 int waiting; // am I waiting for a user-space response?
144 int fd; // what is the user space fd?
146 char url[MAX_URL]; // what is the url describing the device
148 v3_guest_dev_t guestdev; // what is the palacios-side device
150 wait_queue_head_t user_wait_queue; // user space processes waiting on us (should be only one)
151 wait_queue_head_t host_wait_queue; // host threads (should only be one) waiting on user space
153 struct v3_guest *guest; // my guest
154 struct palacios_host_dev_host_request_response *req; // curent request
155 struct palacios_host_dev_host_request_response *resp; // curent response
157 struct list_head node; // for adding me to the list of hostdevs this VM has
161 /**************************************************************************************
163 *************************************************************************************/
165 static void palacios_host_dev_user_free(struct palacios_host_device_user *dev)
180 // Is this structure big enough for the data_size we will use?
182 // THIS FUNCTION CAN BE CALLED WHILE INTERRUPTS ARE OFF
184 static int palacios_bigenough_reqresp(struct palacios_host_dev_host_request_response *r, uint64_t data_size)
189 if (((r->len)-sizeof(struct palacios_host_dev_host_request_response)) < data_size) {
198 // Resize a request/response structure so that it will fit data_size bytes
200 // At the end of this, *r->len >= sizeof(struct)+data_size
202 // THIS FUNCTION MAY SLEEP AS IT CALLS KMALLOC
203 // DO NOT CALL IT WHILE HOLDING A SPIN LOCK WITH INTERRUPTS OFF
205 static int palacios_resize_reqresp(struct palacios_host_dev_host_request_response **r, uint64_t data_size, int copy)
208 DEEP_DEBUG_PRINT("palacios: hostdev: resize 0x%p to %llu\n",*r,data_size);
212 DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n");
213 *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
214 DEEP_DEBUG_PRINT("palacios: hostdev: kmalloc done\n");
216 ERROR("palacios: hostdev: failed to allocate\n");
219 (*r)->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
220 DEEP_DEBUG_PRINT("palacios: hostdev: allocated\n");
224 //let it go if it's big enough
225 uint64_t cur_len = (*r)->len-sizeof(struct palacios_host_dev_host_request_response);
227 if (data_size<=cur_len) {
229 DEEP_DEBUG_PRINT("palacios: hostdev: size ok\n");
232 struct palacios_host_dev_host_request_response *new;
238 new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL);
240 ERROR("palacios: hostdev: failed to reallocate\n");
243 new->len=sizeof(struct palacios_host_dev_host_request_response)+data_size;
245 memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response));
246 new->data_len=(*r)->data_len;
250 DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n");
257 static void cycle_request_response(struct palacios_host_device_user *dev)
259 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response\n");
260 // wake up user side so that polls fall through
261 wake_up_interruptible(&(dev->user_wait_queue));
262 // put us to sleep until the user side wakes us up
263 while (wait_event_interruptible((dev->host_wait_queue), (dev->waiting==0)) != 0) {}
265 DEEP_DEBUG_PRINT("palacios: hostdev: cycle request to response - done\n");
268 static void cycle_response_request(struct palacios_host_device_user *dev)
270 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request\n");
272 wake_up_interruptible(&(dev->host_wait_queue));
273 DEEP_DEBUG_PRINT("palacios: hostdev: cycle response to request - done\n");
277 /*********************************************************************************************
279 Interface to user space
281 *********************************************************************************************/
285 static unsigned int host_dev_poll(struct file * filp,
286 struct poll_table_struct * poll_tb)
289 struct palacios_host_device_user * dev = filp->private_data;
292 SHALLOW_DEBUG_PRINT("palacios: hostdev: poll\n");
294 if (!dev->connected) {
295 ERROR("palcios: hostdev: poll on unconnected device\n");
299 spin_lock_irqsave(&(dev->lock),f);
302 // Yes, we have a request if you want it!
303 spin_unlock_irqrestore(&(dev->lock),f);
304 DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n");
305 return POLLIN | POLLRDNORM;
308 // No request yet, so we need to wait for one to show up.
310 // register ourselves on the user wait queue
311 poll_wait(filp, &(dev->user_wait_queue), poll_tb);
313 spin_unlock_irqrestore(&(dev->lock),f);
315 DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
316 // We will get called again when that queue is woken up
322 static int host_dev_release(struct inode * i, struct file * filp)
324 struct palacios_host_device_user *dev = filp->private_data;
327 INFO("palacios: user side is closing host device \"%s\"\n",dev->url);
329 spin_lock_irqsave(&(dev->lock), f);
331 spin_unlock_irqrestore(&(dev->lock), f);
333 // it is the palacios->host interface's responsibility to ignore
334 // reads/writes until connected is true
340 static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
342 void __user *argp = (void __user *)arg;
344 struct palacios_host_device_user *dev = fp->private_data;
346 DEEP_DEBUG_PRINT("palacios: hostdev: ioctl %u\n",val);
349 if (!dev->connected) {
350 ERROR("palacios: hostdev: ioctl on unconnected device\n");
355 case V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL: {
357 struct palacios_host_dev_user_op op;
359 if (copy_from_user(&op,argp,sizeof(struct palacios_host_dev_user_op))) {
360 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
364 DEEP_DEBUG_PRINT("palacios: hostdev: user request push, type %d\n",op.type);
367 case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: {
368 void *temp = kmalloc(op.len,GFP_KERNEL);
370 DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n");
373 ERROR("palacios: unable to allocate enough for read guest request for host device \"%s\"\n",dev->url);
377 if (v3_host_dev_read_guest_mem(dev->guestdev,
382 ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url);
387 if (copy_to_user(op.data,temp,op.len)) {
388 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
400 case PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST: {
403 DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n");
405 temp = kmalloc(op.len,GFP_KERNEL);
408 ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url);
412 if (copy_from_user(temp,op.data,op.len)) {
413 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
418 if (v3_host_dev_write_guest_mem(dev->guestdev,
423 ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url);
434 case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
436 DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
438 return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq);
443 ERROR("palacios: unknown user request to host device \"%s\"\n",dev->url);
450 case V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL: {
455 DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n");
457 spin_lock_irqsave(&(dev->lock),f);
459 if (!(dev->waiting)) {
460 spin_unlock_irqrestore(&(dev->lock),f);
461 DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n");
462 schedule(); // avoid livelock for polling user space process SUSPICOUS
463 return 0; // no request available now
466 if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) {
467 spin_unlock_irqrestore(&(dev->lock),f);
468 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
469 return -EFAULT; // failed to copy!
473 spin_unlock_irqrestore(&(dev->lock),f);
475 DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
477 return 1; // have request for you
483 case V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL: {
487 spin_lock_irqsave(&(dev->lock),f);
489 DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n");
491 if (!(dev->waiting) || !(dev->req)) {
492 spin_unlock_irqrestore(&(dev->lock),f);
493 DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n");
494 return 0; // no request available now
498 if (copy_to_user(argp,dev->req,dev->req->data_len)) {
499 spin_unlock_irqrestore(&(dev->lock),f);
500 ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
501 return -EFAULT; // failed to copy!
504 spin_unlock_irqrestore(&(dev->lock),f);
506 DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
508 return 1; // copied request for you
512 case V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL: {
515 uint64_t user_datalen;
518 spin_lock_irqsave(&(dev->lock),f);
520 DEEP_DEBUG_PRINT("palacios: hostdev: push response\n");
522 if (!(dev->waiting)) {
523 spin_unlock_irqrestore(&(dev->lock),f);
524 ERROR("palacios: hostdev: no matching request for pushed response\n");
525 return 0; // no request outstanding, so we do not need a response!
528 if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) {
529 spin_unlock_irqrestore(&(dev->lock),f);
530 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
531 return -EFAULT; // failed to copy!
534 if (user_datalen<sizeof(struct palacios_host_dev_host_request_response)) {
536 spin_unlock_irqrestore(&(dev->lock),f);
537 ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url);
541 if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
543 // we drop the lock, turn on interrupts, resize, and then retry
544 DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
546 spin_unlock_irqrestore(&(dev->lock),f);
548 if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) {
549 ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url);
552 // reacquire the lock
553 // There shouldn't be a race here, since there should
554 // be exactly one user space thread giving us a response for this device
555 // and it is blocked waiting for us to finish
556 spin_lock_irqsave(&(dev->lock),f);
557 DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
561 //We only copy data_len bytes from user, but we will
562 //overwrite the len field, so we preserve and then restore
563 old_len = dev->resp->len;
564 if (copy_from_user(dev->resp, argp, user_datalen)) {
565 dev->resp->len=old_len;
566 spin_unlock_irqrestore(&(dev->lock),f);
567 ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url);
568 return -EFAULT; // failed to copy!
570 dev->resp->len=old_len;
572 DEEP_DEBUG_PRINT("palacios: hostdev: valid response pushed\n");
573 // now have valid response!
576 spin_unlock_irqrestore(&(dev->lock),f);
578 // wake the palacios side up so that it sees it
579 cycle_response_request(dev);
586 ERROR("palacios: unknown ioctl for host device \"%s\"\n",dev->url);
596 static struct file_operations host_dev_fops = {
597 .poll = host_dev_poll,
598 .release = host_dev_release,
599 .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 printk("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);
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 **************************************************************************************/
692 static v3_host_dev_t palacios_host_dev_open(char *url,
695 void *host_priv_data)
697 struct v3_guest *guest= (struct v3_guest*)host_priv_data;
698 struct palacios_host_device_user *dev;
701 struct palacios_host_dev * host_dev = NULL;
704 I will create the device in the list and then wait
705 for the user side to attach
713 host_dev = get_vm_ext_data(guest, "HOST_DEV_INTERFACE");
715 if (host_dev == NULL) {
716 printk("Error locating vm host data for HOST_DEV_INTERFACE\n");
721 if (strncasecmp(url,"user:",5)) {
722 ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
726 // Check to see if a device of this url already exists, which would be ugly
727 spin_lock_irqsave(&(host_dev->lock),f1);
728 list_for_each_entry(dev,&(host_dev->devs), node) {
729 if (!strncasecmp(url,dev->url,MAX_URL)) {
731 spin_unlock_irqrestore(&(host_dev->lock),f1);
732 ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
736 spin_unlock_irqrestore(&(host_dev->lock),f1);
739 INFO("palacios: creating host device \"%s\"\n",url);
741 dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL);
744 ERROR("palacios: cannot allocate for host device \"%s\"\n",url);
748 memset(dev,0,sizeof(struct palacios_host_device_user));
750 strncpy(dev->url,url,MAX_URL);
756 spin_lock_init(&(dev->lock));
758 init_waitqueue_head(&(dev->user_wait_queue));
759 init_waitqueue_head(&(dev->host_wait_queue));
761 INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
763 // Insert ourselves into the list
764 spin_lock_irqsave(&(host_dev->lock),f1);
765 list_add(&(dev->node),&(host_dev->devs));
766 spin_unlock_irqrestore(&(host_dev->lock),f1);
769 // Now wait until we are noticed!
770 for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
771 spin_lock_irqsave(&(dev->lock),f2);
773 INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd);
774 spin_unlock_irqrestore(&(dev->lock),f2);
777 spin_unlock_irqrestore(&(dev->lock),f2);
778 ssleep(RENDEZVOUS_RETRY_SECS);
781 ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
783 // get us out of the list
784 spin_lock_irqsave(&(host_dev->lock),f1);
785 list_del(&(dev->node));
786 spin_unlock_irqrestore(&(host_dev->lock),f1);
788 palacios_host_dev_user_free(dev);
793 static int palacios_host_dev_close(v3_host_dev_t hostdev)
795 unsigned long f1, f2;
797 struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
798 struct palacios_host_dev * host_dev = NULL;
800 INFO("palacios: closing host device \"%s\"\n",dev->url);
802 if ((dev == NULL) || (dev->guest == NULL)) {
806 host_dev = get_vm_ext_data(dev->guest, "HOST_DEV_INTERFACE");
809 if (host_dev == NULL) {
813 spin_lock_irqsave(&(host_dev->lock),f1);
815 spin_lock_irqsave(&(dev->lock),f2);
817 if (dev->connected) {
819 // After this, any user side request will return -EFAULT
822 list_del(&(dev->node));
824 spin_unlock_irqrestore(&(dev->lock),f2);
825 spin_unlock_irqrestore(&(host_dev->lock),f1);
827 palacios_host_dev_user_free(dev);
835 static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
840 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
844 DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port);
847 spin_lock_irqsave(&(dev->lock),f);
850 spin_unlock_irqrestore(&(dev->lock),f);
851 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);
855 if (!dev->connected) {
856 spin_unlock_irqrestore(&(dev->lock),f);
857 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
862 // resize request (no data)
863 if (!palacios_bigenough_reqresp(dev->req,0)) {
865 // we drop the lock, turn on interrupts, resize, and then retry
866 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
868 spin_unlock_irqrestore(&(dev->lock),f);
870 if (palacios_resize_reqresp(&(dev->req),0,0)) {
871 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
874 // reacquire the lock
875 // There shouldn't be a race here since there should not be another
876 // request from palacios until this one finishes
877 spin_lock_irqsave(&(dev->lock),f);
878 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
883 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_IO;
885 dev->req->op_len=len;
887 dev->req->conf_addr=0;
888 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
892 spin_unlock_irqrestore(&(dev->lock),f);
894 // hand over to the user space and wait for it to respond
895 cycle_request_response(dev);
897 // We're back! So now we'll hand the response back to Palacios
899 spin_lock_irqsave(&(dev->lock),f);
901 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
903 memcpy(dest,dev->resp->data, op_len);
905 spin_unlock_irqrestore(&(dev->lock),f);
910 static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
915 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
919 DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa);
921 spin_lock_irqsave(&(dev->lock),f);
924 spin_unlock_irqrestore(&(dev->lock),f);
925 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);
928 if (!dev->connected) {
929 spin_unlock_irqrestore(&(dev->lock),f);
930 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
934 // resize request (no data)
935 if (!palacios_bigenough_reqresp(dev->req,0)) {
937 // we drop the lock, turn on interrupts, resize, and then retry
938 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
940 spin_unlock_irqrestore(&(dev->lock),f);
942 if (palacios_resize_reqresp(&(dev->req),0,0)) {
943 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
946 // reacquire the lock
947 // There shouldn't be a race here since there should not be another
948 // request from palacios until this one finishes
949 spin_lock_irqsave(&(dev->lock),f);
950 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
954 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_MEM;
956 dev->req->op_len=len;
958 dev->req->conf_addr=0;
959 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
963 spin_unlock_irqrestore(&(dev->lock),f);
965 // hand over to the user space and wait for it to respond
966 cycle_request_response(dev);
968 // We're back! So now we'll hand the response back to Palacios
970 spin_lock_irqsave(&(dev->lock),f);
972 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
974 memcpy(dest,dev->resp->data, op_len);
976 spin_unlock_irqrestore(&(dev->lock),f);
981 static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
986 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
990 DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
992 spin_lock_irqsave(&(dev->lock),f);
995 spin_unlock_irqrestore(&(dev->lock),f);
996 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);
999 if (!dev->connected) {
1000 spin_unlock_irqrestore(&(dev->lock),f);
1001 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1005 // resize request (no data)
1006 if (!palacios_bigenough_reqresp(dev->req,0)) {
1008 // we drop the lock, turn on interrupts, resize, and then retry
1009 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1011 spin_unlock_irqrestore(&(dev->lock),f);
1013 if (palacios_resize_reqresp(&(dev->req),0,0)) {
1014 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1017 // reacquire the lock
1018 // There shouldn't be a race here since there should not be another
1019 // request from palacios until this one finishes
1020 spin_lock_irqsave(&(dev->lock),f);
1021 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1025 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
1027 dev->req->op_len=len;
1029 dev->req->conf_addr=offset;
1030 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response);
1034 spin_unlock_irqrestore(&(dev->lock),f);
1036 // hand over to the user space and wait for it to respond
1037 cycle_request_response(dev);
1039 // We're back! So now we'll hand the response back to Palacios
1041 spin_lock_irqsave(&(dev->lock),f);
1043 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1045 memcpy(dest,dev->resp->data, op_len);
1047 spin_unlock_irqrestore(&(dev->lock),f);
1053 static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
1058 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1062 DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port);
1064 spin_lock_irqsave(&(dev->lock),f);
1067 spin_unlock_irqrestore(&(dev->lock),f);
1068 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);
1071 if (!dev->connected) {
1072 spin_unlock_irqrestore(&(dev->lock),f);
1073 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1078 if (!palacios_bigenough_reqresp(dev->req,len)) {
1080 // we drop the lock, turn on interrupts, resize, and then retry
1081 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1083 spin_unlock_irqrestore(&(dev->lock),f);
1085 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1086 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1089 // reacquire the lock
1090 // There shouldn't be a race here since there should not be another
1091 // request from palacios until this one finishes
1092 spin_lock_irqsave(&(dev->lock),f);
1093 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1097 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
1098 dev->req->port=port;
1099 dev->req->op_len=len;
1101 dev->req->conf_addr=0;
1102 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1104 memcpy(dev->req->data,src,len);
1108 spin_unlock_irqrestore(&(dev->lock),f);
1110 // hand over to the user space and wait for it to respond
1111 cycle_request_response(dev);
1113 // We're back! So now we'll hand the response back to Palacios
1115 spin_lock_irqsave(&(dev->lock),f);
1117 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1119 spin_unlock_irqrestore(&(dev->lock),f);
1125 static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
1130 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1134 DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
1136 spin_lock_irqsave(&(dev->lock),f);
1139 spin_unlock_irqrestore(&(dev->lock),f);
1140 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);
1143 if (!dev->connected) {
1144 spin_unlock_irqrestore(&(dev->lock),f);
1145 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1150 if (!palacios_bigenough_reqresp(dev->req,len)) {
1152 // we drop the lock, turn on interrupts, resize, and then retry
1153 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1155 spin_unlock_irqrestore(&(dev->lock),f);
1157 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1158 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1161 // reacquire the lock
1162 // There shouldn't be a race here since there should not be another
1163 // request from palacios until this one finishes
1164 spin_lock_irqsave(&(dev->lock),f);
1165 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1169 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
1171 dev->req->op_len=len;
1173 dev->req->conf_addr=0;
1174 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1176 memcpy(dev->req->data,src,len);
1180 spin_unlock_irqrestore(&(dev->lock),f);
1182 // hand over to the user space and wait for it to respond
1183 cycle_request_response(dev);
1185 // We're back! So now we'll hand the response back to Palacios
1187 spin_lock_irqsave(&(dev->lock),f);
1189 op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
1191 spin_unlock_irqrestore(&(dev->lock),f);
1199 static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
1204 struct palacios_host_device_user *dev = (struct palacios_host_device_user *)hostdev;
1208 DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset);
1210 spin_lock_irqsave(&(dev->lock),f);
1213 spin_unlock_irqrestore(&(dev->lock),f);
1214 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);
1217 if (!dev->connected) {
1218 spin_unlock_irqrestore(&(dev->lock),f);
1219 ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
1224 if (!palacios_bigenough_reqresp(dev->req,len)) {
1226 // we drop the lock, turn on interrupts, resize, and then retry
1227 DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url);
1229 spin_unlock_irqrestore(&(dev->lock),f);
1231 if (palacios_resize_reqresp(&(dev->req),len,0)) {
1232 ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
1235 // reacquire the lock
1236 // There shouldn't be a race here since there should not be another
1237 // request from palacios until this one finishes
1238 spin_lock_irqsave(&(dev->lock),f);
1239 DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
1243 dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
1245 dev->req->op_len=len;
1247 dev->req->conf_addr=offset;
1248 dev->req->data_len=sizeof(struct palacios_host_dev_host_request_response)+len;
1250 memcpy(dev->req->data,src,len);
1254 spin_unlock_irqrestore(&(dev->lock),f);
1256 // hand over to the user space and wait for it to respond
1257 cycle_request_response(dev);
1259 // We're back! So now we'll hand the response back to Palacios
1261 spin_lock_irqsave(&(dev->lock),f);
1263 op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
1265 spin_unlock_irqrestore(&(dev->lock),f);
1271 static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
1281 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
1282 .open = palacios_host_dev_open,
1283 .close = palacios_host_dev_close,
1284 .read_io = palacios_host_dev_read_io,
1285 .write_io = palacios_host_dev_write_io,
1286 .read_mem = palacios_host_dev_read_mem,
1287 .write_mem = palacios_host_dev_write_mem,
1288 .read_config = palacios_host_dev_read_conf,
1289 .write_config = palacios_host_dev_write_conf,
1290 .ack_irq = palacios_host_dev_ack_irq,
1295 static int host_dev_init( void ) {
1296 V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
1302 static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
1303 struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL);
1306 INIT_LIST_HEAD(&(host_dev->devs));
1307 spin_lock_init(&(host_dev->lock));
1309 *vm_data = host_dev;
1312 add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
1321 static struct linux_ext host_dev_ext = {
1322 .name = "HOST_DEV_INTERFACE",
1323 .init = host_dev_init,
1325 .guest_init = host_dev_guest_init,
1326 .guest_deinit = NULL
1330 register_extension(&host_dev_ext);