Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Cleanup of locking in host device interface
[palacios.git] / linux_module / iface-host-dev.c
index 6edc26b..c9c586e 100644 (file)
@@ -126,14 +126,14 @@ struct palacios_host_dev {
 #define DEEP_DEBUG    0
 #define SHALLOW_DEBUG 0
 
-#if DEEP_DEBUG
-#define DEEP_DEBUG_PRINT(fmt, args...) DEBUG((fmt), ##args)
+#if DEEP_DEBUG == 1
+#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...) INFO((fmt), ##args)
+#if SHALLOW_DEBUG == 1
+#define SHALLOW_DEBUG_PRINT(fmt, args...) INFO(fmt, ##args)
 #else
 #define SHALLOW_DEBUG_PRINT(fmt, args...) 
 #endif
@@ -149,6 +149,7 @@ struct palacios_host_device_user {
     char     url[MAX_URL]; // what is the url describing the device
 
     v3_guest_dev_t guestdev; // what is the palacios-side device
+    v3_guest_dev_intr_t guestintr; // what is the palacios-side device interrupt info
 
     wait_queue_head_t  user_wait_queue; // user space processes waiting on us (should be only one)
     wait_queue_head_t  host_wait_queue; // host threads (should only be one) waiting on user space
@@ -301,6 +302,10 @@ static unsigned int host_dev_poll(struct file * filp,
 
     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!
        palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
@@ -310,9 +315,6 @@ static unsigned int host_dev_poll(struct file * filp,
 
     // 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);
-
     palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
 
     DEEP_DEBUG_PRINT("palacios: hostdev: poll delayed\n");
@@ -433,11 +435,18 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
                }
                    break;
 
-               case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST: {
+               case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_RAISE_GUEST: {
 
-                   DEEP_DEBUG_PRINT("palacios: hostdev: irq guest\n");
+                   DEEP_DEBUG_PRINT("palacios: hostdev: irq raise guest\n");
 
-                   return  v3_host_dev_raise_irq(dev, dev->guestdev, op.irq);
+                   return  v3_host_dev_raise_irq(dev, dev->guestdev, dev->guestintr, op.irq);
+               }
+                   break;
+               case PALACIOS_HOST_DEV_USER_REQUEST_IRQ_LOWER_GUEST: {
+
+                   DEEP_DEBUG_PRINT("palacios: hostdev: irq lower guest\n");
+
+                   return  v3_host_dev_lower_irq(dev, dev->guestdev, dev->guestintr, op.irq);
                }
                    break;
 
@@ -464,7 +473,11 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
                schedule();  // avoid livelock for polling user space process  SUSPICOUS
                return 0; // no request available now
            } 
-           
+
+           // safe to unlock here since if we are in the waiting state
+           // the palacios side will not modify the request
+           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+
            if (copy_to_user(argp,&(dev->req->data_len),sizeof(uint64_t))) { 
                palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
                ERROR("palacios: unable to copy to user for host device \"%s\"\n",dev->url);
@@ -472,8 +485,6 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
 
            }
            
-           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
            DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
 
            return 1; // have request for you
@@ -496,15 +507,15 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
                return 0; // no request available now
            } 
 
+           // Safe to unlock here since if we are in the waiting 
+           // state, the request will not be modified by the palacios side
+           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
            
            if (copy_to_user(argp,dev->req,dev->req->data_len)) { 
-               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!
            }
     
-           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
            DEEP_DEBUG_PRINT("palacios: hostdev: request pulled\n");
            
            return 1; // copied request for you
@@ -527,37 +538,31 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
                return 0; // no request outstanding, so we do not need a response!
            }
            
+           // Safe to unlock here as the palacios side will not
+           // modify the request or copy the response until we
+           // reset dev->waiting
+           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+
            if (copy_from_user(&user_datalen,argp,sizeof(uint64_t))) { 
-               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_datalen<sizeof(struct palacios_host_dev_host_request_response)) { 
                // bad user
-               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;
            }
 
            if (!palacios_bigenough_reqresp(dev->resp,user_datalen-sizeof(struct palacios_host_dev_host_request_response))) {
                // not enough room.
-               // 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);
+               DEEP_DEBUG_PRINT("palacios: response not big enough, resizing on device \"%s\"\n",dev->url);
 
-               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);
                    return -EFAULT;
-               } else {
-                   // reacquire the lock
-                   // 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
-                   palacios_spinlock_lock_irqsave(&(dev->lock),f);
-                   DEEP_DEBUG_PRINT("palacios: reacuired lock on device \"%s\"\n",dev->url);
-               }
+               } 
            }
 
            //We only copy data_len bytes from user, but we will
@@ -565,7 +570,6 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
            old_len = dev->resp->len;
            if (copy_from_user(dev->resp, argp, user_datalen)) { 
                dev->resp->len=old_len;
-               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!
            } 
@@ -575,8 +579,6 @@ static long host_dev_ioctl(struct file * fp, unsigned int val, unsigned long arg
            // now have valid response!
            dev->waiting=0;
 
-           palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
            // wake the palacios side up so that it sees it
            cycle_response_request(dev);
 
@@ -727,6 +729,7 @@ static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
 static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
                                                     v3_bus_class_t bus,
                                                     v3_guest_dev_t gdev,
+                                                    v3_guest_dev_intr_t gintr,
                                                     void *host_priv_data)
 {
     struct v3_guest *guest= (struct v3_guest*)host_priv_data;
@@ -785,6 +788,8 @@ static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
     
     dev->guestdev = gdev;
     
+    dev->guestintr = gintr;
+    
     dev->guest = guest;
 
     palacios_spinlock_init(&(dev->lock));
@@ -839,6 +844,8 @@ static int palacios_host_dev_close(v3_host_dev_t hostdev)
     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;
@@ -858,14 +865,11 @@ 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);
            
-
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
-    
     if (palacios_host_dev_rendezvous(dev)) {
-       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;
     }
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
 
     if (dev->waiting) { 
        palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
@@ -873,26 +877,19 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
        return 0;
     }
 
-    
+    // if we're not waiting on user, we have access to
+    // to the request and response fields
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
     
     // resize request (no data)
     if (!palacios_bigenough_reqresp(dev->req,0)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),0,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
-       }
+       } 
     }
     
 
@@ -905,21 +902,17 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
 
     dev->waiting=1;
     
-    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
-
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
+    // no need to lock, we own the response since 
+    // waiting is now 0
 
     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
 
     memcpy(dest,dev->resp->data, op_len);
     
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
 
@@ -934,37 +927,31 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
 
     DEEP_DEBUG_PRINT("palacios: hostdev: read mem  0x%p\n",gpa);
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
     
     if (palacios_host_dev_rendezvous(dev)) {
-       palacios_spinlock_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;
     }
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
 
     if (dev->waiting) { 
        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;
     }
+
+    // We now are assured to have ownership over request
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
     
     // resize request (no data)
     if (!palacios_bigenough_reqresp(dev->req,0)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),0,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
        }
     }
 
@@ -977,21 +964,15 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
 
     dev->waiting=1;
     
-    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
 
-    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);
     
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
 
@@ -1004,15 +985,15 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
     unsigned long f;
     uint64_t op_len;
 
-    DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p\n",(void*)offset);
+    DEEP_DEBUG_PRINT("palacios: hostdev: read conf 0x%p (len=%lld)\n",(void*)offset, len);
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
     
     if (palacios_host_dev_rendezvous(dev)) {
-       palacios_spinlock_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;
     }
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
 
     if (dev->waiting) { 
        palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
@@ -1020,24 +1001,18 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
        return 0;
     }
     
+    // Now have exclusive access to request
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+
     // resize request (no data)
     if (!palacios_bigenough_reqresp(dev->req,0)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),0,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
-       }
+       } 
     }
 
     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_READ_CONF;
@@ -1049,21 +1024,15 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
 
     dev->waiting=1;
     
-    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
 
-    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);
     
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
 
@@ -1079,13 +1048,13 @@ 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);
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
     
     if (palacios_host_dev_rendezvous(dev)) {
-       palacios_spinlock_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;
     }
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
 
     if (dev->waiting) { 
        palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
@@ -1093,24 +1062,18 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
        return 0;
     }
 
+    // have exclusive access to request
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       
     // resize request 
     if (!palacios_bigenough_reqresp(dev->req,len)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),len,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
-       }
+       } 
     }
 
     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO;
@@ -1124,19 +1087,13 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
 
     dev->waiting=1;
 
-    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
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
-
     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
 
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
 
@@ -1152,38 +1109,33 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
 
     DEEP_DEBUG_PRINT("palacios: hostdev: write mem 0x%p\n",gpa);
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
     
     if (palacios_host_dev_rendezvous(dev)) {
-       palacios_spinlock_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;
     }
 
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
+
     if (dev->waiting) { 
        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;
     }
     
+    // Now have exclusive access to request
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+    
     // resize request 
     if (!palacios_bigenough_reqresp(dev->req,len)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),len,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
-       }
+       } 
     }
 
     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_MEM;
@@ -1197,19 +1149,13 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
 
     dev->waiting=1;
     
-    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
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
-
     op_len= dev->resp->op_len < len ? dev->resp->op_len : len ;
 
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
 
@@ -1227,13 +1173,13 @@ 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);
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
     
     if (palacios_host_dev_rendezvous(dev)) {
-       palacios_spinlock_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;
     }
+    palacios_spinlock_lock_irqsave(&(dev->lock),f);
 
     if (dev->waiting) { 
        palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
@@ -1241,24 +1187,18 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
        return 0;
     }
     
+    // Have exclusive access to request
+    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+
     // resize request 
     if (!palacios_bigenough_reqresp(dev->req,len)) {
        // not enough room.
-       // 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);
-       
-       palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
+       DEEP_DEBUG_PRINT("palacios: request not big enough, resizing on device \"%s\"\n",dev->url);
        
        if (palacios_resize_reqresp(&(dev->req),len,0)) {
            ERROR("palacios: cannot resize for request on device \"%s\"\n",dev->url);
            return 0;
-       } else {
-           // reacquire the lock
-           // There shouldn't be a race here since there should not be another
-           // request from palacios until this one finishes
-           palacios_spinlock_lock_irqsave(&(dev->lock),f);
-           DEEP_DEBUG_PRINT("palacios: reacquired lock on device \"%s\"\n",dev->url);
-       }
+       } 
     }
 
     dev->req->type=PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_CONF;
@@ -1271,20 +1211,14 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
     memcpy(dev->req->data,src,len);
 
     dev->waiting=1;
-    
-    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
 
-    palacios_spinlock_lock_irqsave(&(dev->lock),f);
-
     op_len = dev->resp->op_len < len ? dev->resp->op_len : len ;
 
-    palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
     return op_len;
 }
  
@@ -1320,6 +1254,11 @@ 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 = palacios_alloc(sizeof(struct palacios_host_dev));
 
@@ -1343,7 +1282,10 @@ 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) {
 
-    palacios_free(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;
 }
 
@@ -1353,7 +1295,7 @@ static int host_dev_guest_deinit(struct v3_guest * guest, void * vm_data) {
 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 = host_dev_guest_deinit
 };