#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
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);
}
- palacios_spinlock_unlock_irqrestore(&(dev->lock),f);
-
DEEP_DEBUG_PRINT("palacios: hostdev: have request\n");
return 1; // have request for you
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
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
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!
}
// 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);
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);
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);
- }
+ }
}
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;
}
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);
}
}
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;
}
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);
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;
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;
}
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);
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;
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;
}
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;
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;
}
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);
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;
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;
}