X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fiface-host-dev.c;h=680d7537515f90192a36fff067af73d8c95a10c0;hb=e8ee9e1536b3fa2e69f5537a90f5e034e9529248;hp=c7c2567dff58f26451335fc85698a8d4c4b5cba6;hpb=59a2f6308c5077481e184c4cb5792c082cf2ca3a;p=palacios.git diff --git a/linux_module/iface-host-dev.c b/linux_module/iface-host-dev.c index c7c2567..680d753 100644 --- a/linux_module/iface-host-dev.c +++ b/linux_module/iface-host-dev.c @@ -127,21 +127,18 @@ struct palacios_host_dev { #define SHALLOW_DEBUG 0 #if DEEP_DEBUG -#define DEEP_DEBUG_PRINT(fmt, args...) printk((fmt), ##args) +#define DEEP_DEBUG_PRINT(fmt, args...) DEBUG((fmt), ##args) #else #define DEEP_DEBUG_PRINT(fmt, args...) #endif #if SHALLOW_DEBUG -#define SHALLOW_DEBUG_PRINT(fmt, args...) printk((fmt), ##args) +#define SHALLOW_DEBUG_PRINT(fmt, args...) INFO((fmt), ##args) #else #define SHALLOW_DEBUG_PRINT(fmt, args...) #endif -#define ERROR(fmt, args...) printk((fmt), ##args) -#define INFO(fmt, args...) printk((fmt), ##args) - struct palacios_host_device_user { spinlock_t lock; int connected; // is the user space connected to this? @@ -171,14 +168,14 @@ struct palacios_host_device_user { static void palacios_host_dev_user_free(struct palacios_host_device_user *dev) { if (dev->req) { - kfree(dev->req); + palacios_free(dev->req); dev->req=0; } if (dev->resp) { - kfree(dev->resp); + palacios_free(dev->resp); dev->resp=0; } - kfree(dev); + palacios_free(dev); } @@ -216,8 +213,8 @@ static int palacios_resize_reqresp(struct palacios_host_dev_host_request_respons if ((*r)==0) { // allocate it DEEP_DEBUG_PRINT("palacios: hostdev: attempt alloc\n"); - *r = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL); - DEEP_DEBUG_PRINT("palacios: hostdev: kmalloc done\n"); + *r = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size); + DEEP_DEBUG_PRINT("palacios: hostdev: palacios_alloc done\n"); if ((*r)==0) { ERROR("palacios: hostdev: failed to allocate\n"); return -1; @@ -238,10 +235,10 @@ static int palacios_resize_reqresp(struct palacios_host_dev_host_request_respons struct palacios_host_dev_host_request_response *new; if (!copy) { - kfree(*r); + palacios_free(*r); *r=0; } - new = kmalloc(sizeof(struct palacios_host_dev_host_request_response)+data_size,GFP_KERNEL); + new = palacios_alloc(sizeof(struct palacios_host_dev_host_request_response)+data_size); if (!new) { ERROR("palacios: hostdev: failed to reallocate\n"); return -1; @@ -250,7 +247,7 @@ static int palacios_resize_reqresp(struct palacios_host_dev_host_request_respons if (copy) { memcpy(new->data,(*r)->data,(*r)->data_len-sizeof(struct palacios_host_dev_host_request_response)); new->data_len=(*r)->data_len; - kfree(*r); + palacios_free(*r); } *r=new; DEEP_DEBUG_PRINT("palacios: hostdev: reallocated\n"); @@ -302,21 +299,22 @@ static unsigned int host_dev_poll(struct file * filp, return -EFAULT; } - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); + + + // register ourselves on the user wait queue + poll_wait(filp, &(dev->user_wait_queue), poll_tb); if (dev->waiting) { // Yes, we have a request if you want it! - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: poll done immediate\n"); return POLLIN | POLLRDNORM; } // No request yet, so we need to wait for one to show up. - // register ourselves on the user wait queue - poll_wait(filp, &(dev->user_wait_queue), poll_tb); - - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n"); // We will get called again when that queue is woken up @@ -332,9 +330,9 @@ static int host_dev_release(struct inode * i, struct file * filp) INFO("palacios: user side is closing host device \"%s\"\n",dev->url); - spin_lock_irqsave(&(dev->lock), f); + palacios_spinlock_lock_irqsave(&(dev->lock), f); dev->connected = 0; - spin_unlock_irqrestore(&(dev->lock), f); + palacios_spinlock_unlock_irqrestore(&(dev->lock), f); // it is the palacios->host interface's responsibility to ignore // reads/writes until connected is true @@ -342,7 +340,7 @@ static int host_dev_release(struct inode * i, struct file * filp) return 0; } -static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg) +static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg) { void __user *argp = (void __user *)arg; @@ -370,7 +368,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u switch (op.type) { case PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST: { - void *temp = kmalloc(op.len,GFP_KERNEL); + void *temp = palacios_alloc(op.len); DEEP_DEBUG_PRINT("palacios: hostdev: read guest\n"); @@ -379,23 +377,23 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u return -EFAULT; } - if (v3_host_dev_read_guest_mem(dev->guestdev, - dev, + if (v3_host_dev_read_guest_mem(dev, + dev->guestdev, op.gpa, temp, op.len) != op.len) { ERROR("palacios: unable to read enough from guest for host device \"%s\"\n",dev->url); - kfree(temp); + palacios_free(temp); return -EFAULT; } if (copy_to_user(op.data,temp,op.len)) { ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url); - kfree(temp); + palacios_free(temp); return -EFAULT; } - kfree(temp); + palacios_free(temp); return op.len; } @@ -407,7 +405,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u DEEP_DEBUG_PRINT("palacios: hostdev: write guest\n"); - temp = kmalloc(op.len,GFP_KERNEL); + temp = palacios_alloc(op.len); if (!temp) { ERROR("palacios: unable to allocate enough for write guest request for host device \"%s\"\n",dev->url); @@ -416,21 +414,21 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u if (copy_from_user(temp,op.data,op.len)) { ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url); - kfree(temp); + palacios_free(temp); return -EFAULT; } - if (v3_host_dev_write_guest_mem(dev->guestdev, - dev, + if (v3_host_dev_write_guest_mem(dev, + dev->guestdev, op.gpa, temp, op.len) != op.len) { ERROR("palacios: unable to write enough to guest for host device \"%s\"\n",dev->url); - kfree(temp); + palacios_free(temp); return -EFAULT; } - kfree(temp); + palacios_free(temp); return op.len; } @@ -440,7 +438,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n"); - return v3_host_dev_raise_irq(dev->guestdev, dev, op.irq); + return v3_host_dev_raise_irq(dev, dev->guestdev, op.irq); } break; @@ -459,23 +457,23 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u DEEP_DEBUG_PRINT("palacios: hostdev: request size of request\n"); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (!(dev->waiting)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: no request available\n"); schedule(); // avoid livelock for polling user space process SUSPICOUS return 0; // no request available now } if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url); return -EFAULT; // failed to copy! } - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: have request\n"); @@ -489,24 +487,24 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u unsigned long f; - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: pull request\n"); if (!(dev->waiting) || !(dev->req)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: no request to pull\n"); return 0; // no request available now } if (copy_to_user(argp,dev->req,dev->req->data_len)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url); return -EFAULT; // failed to copy! } - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n"); @@ -520,25 +518,25 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u uint64_t user_datalen; uint64_t old_len; - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: hostdev: push response\n"); if (!(dev->waiting)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: hostdev: no matching request for pushed response\n"); return 0; // no request outstanding, so we do not need a response! } if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url); return -EFAULT; // failed to copy! } if (user_datalenlock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: user has response that is too small on host device \"%s\"\n",dev->url); return -EFAULT; } @@ -548,7 +546,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: response not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->resp),user_datalen-sizeof(struct palacios_host_dev_host_request_response),0)) { ERROR("palacios: unable to resize to accept response of size %llu from user for host device \"%s\"\n",user_datalen,dev->url); @@ -558,7 +556,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u // There shouldn't be a race here, since there should // be exactly one user space thread giving us a response for this device // and it is blocked waiting for us to finish - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url); } } @@ -568,7 +566,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u old_len = dev->resp->len; if (copy_from_user(dev->resp, argp, user_datalen)) { dev->resp->len=old_len; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: unable to copy from user for host device \"%s\"\n",dev->url); return -EFAULT; // failed to copy! } @@ -578,7 +576,7 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u // now have valid response! dev->waiting=0; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // wake the palacios side up so that it sees it cycle_response_request(dev); @@ -595,19 +593,11 @@ static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, u } -static long host_dev_compat_ioctl(struct file * filp, unsigned int ioctl, unsigned long arg) -{ - return host_dev_ioctl(NULL, filp, ioctl, arg); -} - static struct file_operations host_dev_fops = { .poll = host_dev_poll, .release = host_dev_release, -#ifdef HAVE_COMPAT_IOCTL - .compat_ioctl = host_dev_compat_ioctl, -#else - .ioctl = host_dev_ioctl, -#endif + .compat_ioctl = host_dev_ioctl, + .unlocked_ioctl = host_dev_ioctl, }; @@ -624,7 +614,7 @@ static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned if (copy_from_user(url, argp, MAX_URL)) { - printk("copy from user error getting url for host device connect...\n"); + ERROR("copy from user error getting url for host device connect...\n"); return -EFAULT; } @@ -640,43 +630,43 @@ static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned // URL. If we don't find it after a while, we give up for (i=0;ilock),f1); + palacios_spinlock_lock_irqsave(&(host_dev->lock),f1); list_for_each_entry(dev,&(host_dev->devs), node) { if (!strncasecmp(url,dev->url,MAX_URL)) { // found it - spin_lock_irqsave(&(dev->lock),f2); + palacios_spinlock_lock_irqsave(&(dev->lock),f2); if (dev->connected) { ERROR("palacios: device for \"%s\" is already connected!\n",url); - spin_unlock_irqrestore(&(dev->lock),f2); - spin_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f2); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1); return -1; } else { dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0); if (dev->fd<0) { ERROR("palacios: cannot create fd for device \"%s\"\n",url); - spin_unlock_irqrestore(&(dev->lock),f2); - spin_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f2); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1); return -1; } dev->connected=1; dev->waiting=0; if (dev->req) { - kfree(dev->req); + palacios_free(dev->req); dev->req=0; } if (dev->resp) { - kfree(dev->resp); + palacios_free(dev->resp); dev->resp=0; } INFO("palacios: connected fd for device \"%s\"\n",url); - spin_unlock_irqrestore(&(dev->lock),f2); - spin_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f2); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1); return dev->fd; } - spin_unlock_irqrestore(&(dev->lock),f2); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f2); } } - spin_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1); ssleep(RENDEZVOUS_RETRY_SECS); } @@ -716,13 +706,13 @@ static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev) // Now wait until we are noticed! for (i=0;ilock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (dev->connected) { INFO("palacios: connection with user side established for host device \"%s\" fd=%d\n",dev->url,dev->fd); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return 0; } - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ssleep(RENDEZVOUS_RETRY_SECS); } @@ -758,7 +748,7 @@ static v3_host_dev_t palacios_host_dev_open_deferred(char *url, host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE"); if (host_dev == NULL) { - printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n"); + ERROR("Error locating vm host data for HOST_DEVICE_INTERFACE\n"); return 0; } @@ -769,21 +759,21 @@ static v3_host_dev_t palacios_host_dev_open_deferred(char *url, } // Check to see if a device of this url already exists, which would be ugly - spin_lock_irqsave(&(host_dev->lock),f); + palacios_spinlock_lock_irqsave(&(host_dev->lock),f); list_for_each_entry(dev,&(host_dev->devs), node) { if (!strncasecmp(url,dev->url,MAX_URL)) { // found it - spin_unlock_irqrestore(&(host_dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f); ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url); return NULL; } } - spin_unlock_irqrestore(&(host_dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f); INFO("palacios: creating host device \"%s\"\n",url); - dev = kmalloc(sizeof(struct palacios_host_device_user),GFP_KERNEL); + dev = palacios_alloc(sizeof(struct palacios_host_device_user)); if (!dev) { ERROR("palacios: cannot allocate for host device \"%s\"\n",url); @@ -798,15 +788,15 @@ static v3_host_dev_t palacios_host_dev_open_deferred(char *url, dev->guest = guest; - spin_lock_init(&(dev->lock)); + palacios_spinlock_init(&(dev->lock)); init_waitqueue_head(&(dev->user_wait_queue)); init_waitqueue_head(&(dev->host_wait_queue)); // Insert ourselves into the list - spin_lock_irqsave(&(host_dev->lock),f); + palacios_spinlock_lock_irqsave(&(host_dev->lock),f); list_add(&(dev->node),&(host_dev->devs)); - spin_unlock_irqrestore(&(host_dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f); INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url); @@ -836,9 +826,9 @@ static int palacios_host_dev_close(v3_host_dev_t hostdev) return -1; } - spin_lock_irqsave(&(host_dev->lock),f1); + palacios_spinlock_lock_irqsave(&(host_dev->lock),f1); - spin_lock_irqsave(&(dev->lock),f2); + palacios_spinlock_lock_irqsave(&(dev->lock),f2); if (dev->connected) { dev->connected=0; @@ -847,9 +837,11 @@ static int palacios_host_dev_close(v3_host_dev_t hostdev) list_del(&(dev->node)); - spin_unlock_irqrestore(&(dev->lock),f2); - spin_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f2); + palacios_spinlock_unlock_irqrestore(&(host_dev->lock),f1); + palacios_spinlock_deinit(&(dev->lock)); + palacios_host_dev_user_free(dev); return 0; @@ -870,16 +862,16 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: read io port 0x%x\n",port); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -892,7 +884,7 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),0,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -901,7 +893,7 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -916,20 +908,20 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len = dev->resp->op_len < len ? dev->resp->op_len : len ; memcpy(dest,dev->resp->data, op_len); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -945,16 +937,16 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: read mem 0x%p\n",gpa); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -965,7 +957,7 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),0,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -974,7 +966,7 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -988,20 +980,20 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len = dev->resp->op_len < len ? dev->resp->op_len : len ; memcpy(dest,dev->resp->data, op_len); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -1017,16 +1009,16 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -1037,7 +1029,7 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),0,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -1046,7 +1038,7 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -1060,20 +1052,20 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len = dev->resp->op_len < len ? dev->resp->op_len : len ; memcpy(dest,dev->resp->data, op_len); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -1090,16 +1082,16 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: write io port 0x%x \n",port); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -1110,7 +1102,7 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),len,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -1119,7 +1111,7 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -1135,18 +1127,18 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len = dev->resp->op_len < len ? dev->resp->op_len : len ; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -1163,16 +1155,16 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -1183,7 +1175,7 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),len,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -1192,7 +1184,7 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -1208,18 +1200,18 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len= dev->resp->op_len < len ? dev->resp->op_len : len ; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -1238,16 +1230,16 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev, DEEP_DEBUG_PRINT("palacios: hostdev: write conf 0x%p\n",(void*)offset); - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); if (palacios_host_dev_rendezvous(dev)) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); ERROR("palacios: ignoring request as user side is not connected (and did not rendezvous) for host device \"%s\"\n",dev->url); return 0; } if (dev->waiting) { - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); 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); return 0; } @@ -1258,7 +1250,7 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev, // we drop the lock, turn on interrupts, resize, and then retry DEEP_DEBUG_PRINT("palacios: request not big enough, dropping lock to resize on device \"%s\"\n",dev->url); - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); if (palacios_resize_reqresp(&(dev->req),len,0)) { ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url); @@ -1267,7 +1259,7 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev, // reacquire the lock // There shouldn't be a race here since there should not be another // request from palacios until this one finishes - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url); } } @@ -1283,18 +1275,18 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev, dev->waiting=1; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); // hand over to the user space and wait for it to respond cycle_request_response(dev); // We're back! So now we'll hand the response back to Palacios - spin_lock_irqsave(&(dev->lock),f); + palacios_spinlock_lock_irqsave(&(dev->lock),f); op_len = dev->resp->op_len < len ? dev->resp->op_len : len ; - spin_unlock_irqrestore(&(dev->lock),f); + palacios_spinlock_unlock_irqrestore(&(dev->lock),f); return op_len; } @@ -1331,8 +1323,13 @@ static int host_dev_init( void ) { } +static int host_dev_deinit(void) { + // nothing to do + return 0; +} + static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) { - struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL); + struct palacios_host_dev * host_dev = palacios_alloc(sizeof(struct palacios_host_dev)); if (!host_dev) { ERROR("palacios: failed to do guest_init for host device\n"); @@ -1341,7 +1338,7 @@ static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) { INIT_LIST_HEAD(&(host_dev->devs)); - spin_lock_init(&(host_dev->lock)); + palacios_spinlock_init(&(host_dev->lock)); *vm_data = host_dev; @@ -1352,15 +1349,24 @@ static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) { } +static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) { + + struct palacios_host_dev * host_dev = (struct palacios_host_dev *) vm_data; + remove_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT); + palacios_spinlock_deinit(&(host_dev->lock)); + palacios_free(host_dev); + return 0; +} + static struct linux_ext host_dev_ext = { .name = "HOST_DEVICE_INTERFACE", .init = host_dev_init, - .deinit = NULL, + .deinit = host_dev_deinit, .guest_init = host_dev_guest_init, - .guest_deinit = NULL + .guest_deinit = host_dev_guest_deinit };