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.


Revised host device support to work with new extension model and
Peter Dinda [Fri, 10 Jun 2011 16:28:41 +0000 (11:28 -0500)]
startup ordering

User side of the host device now supports deferred rendezvous.
This also means it is possible to disconnect and reconnect
the user side.   The semantics for this with respect to synchronizing
palacios-side and user-side device state are undefined, however.

linux_module/palacios-graphics-console.c
linux_module/palacios-host-dev.c

index e5d4918..3408fe7 100644 (file)
@@ -75,10 +75,10 @@ static v3_graphics_console_t g_open(void * priv_data,
        return 0;
     }
 
-    gc = get_vm_ext_data(guest, "GFX_CONSOLE_INTERFACE");
+    gc = get_vm_ext_data(guest, "GRAPHICS_CONSOLE_INTERFACE");
     
     if (gc == NULL) {
-       printk("ERROR: Could not locate gfx console data for extension GFX_CONSOLE_INTERFACE\n");
+       printk("ERROR: Could not locate gfx console data for extension GRAPHICS_CONSOLE_INTERFACE\n");
        return 0;
     }
 
@@ -366,7 +366,7 @@ static int gfx_console_guest_init(struct v3_guest * guest, void ** vm_data) {
 
 
 static struct linux_ext gfx_cons_ext = {
-    .name = "GFX_CONSOLE_INTERFACE",
+    .name = "GRAPHICS_CONSOLE_INTERFACE",
     .init = gfx_console_init,
     .deinit = NULL,
     .guest_init = gfx_console_guest_init,
index f92f115..e560889 100644 (file)
         // 1 on success, negative on error
      }
     
+     Note that the current model has deferred rendezvous and allows
+     for user-side device disconnection and reconnection.  It is important
+     to note that this implementation does NOT deal with state discrepency
+     between the palacios-side and the user-side.   For example, a user-side
+     device can disconnect, a palacios-side request can then fail, and 
+     when the user-side device reconnects, it is unaware of this failure.  
 
 */
 
@@ -689,16 +695,50 @@ static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned
 
 **************************************************************************************/
 
-static v3_host_dev_t palacios_host_dev_open(char *url,
-                                           v3_bus_class_t bus,
-                                           v3_guest_dev_t gdev,
-                                           void *host_priv_data)
+
+/* Attempt to rendezvous with the user device if no device is currently connected */
+static int palacios_host_dev_rendezvous(struct palacios_host_device_user *dev)
+{
+    unsigned long f;
+    int i;
+
+    if (dev->connected) { 
+       return 0;
+    }
+
+   
+    INFO("palacios: attempting new rendezvous for host device \"%s\"\n",dev->url);
+
+    // Now wait until we are noticed!
+    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
+       spin_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);
+           return 0;
+       }
+       spin_unlock_irqrestore(&(dev->lock),f);
+       ssleep(RENDEZVOUS_RETRY_SECS);
+    }
+    
+    ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",dev->url);
+
+    // We stay in the list because a future rendezvous might happen
+    
+    return -1;
+}
+
+
+/* Creates the device without rendezvous */
+static v3_host_dev_t palacios_host_dev_open_deferred(char *url,
+                                                    v3_bus_class_t bus,
+                                                    v3_guest_dev_t gdev,
+                                                    void *host_priv_data)
 {
     struct v3_guest *guest= (struct v3_guest*)host_priv_data;
     struct palacios_host_device_user *dev;
-    unsigned long f1,f2;
-    int i;
     struct palacios_host_dev * host_dev = NULL;
+    unsigned long f;
 
     /*
       I will create the device in the list and then wait
@@ -710,10 +750,10 @@ static v3_host_dev_t palacios_host_dev_open(char *url,
     }
     
 
-    host_dev = get_vm_ext_data(guest, "HOST_DEV_INTERFACE");
+    host_dev = get_vm_ext_data(guest, "HOST_DEVICE_INTERFACE");
 
     if (host_dev == NULL) {
-       printk("Error locating vm host data for HOST_DEV_INTERFACE\n");
+       printk("Error locating vm host data for HOST_DEVICE_INTERFACE\n");
        return 0;
     }
 
@@ -724,16 +764,16 @@ static v3_host_dev_t palacios_host_dev_open(char *url,
     }
 
     // Check to see if a device of this url already exists, which would be ugly
-    spin_lock_irqsave(&(host_dev->lock),f1);
+    spin_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),f1);
+           spin_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),f1);
+    spin_unlock_irqrestore(&(host_dev->lock),f);
 
 
     INFO("palacios: creating host device \"%s\"\n",url);
@@ -758,38 +798,19 @@ static v3_host_dev_t palacios_host_dev_open(char *url,
     init_waitqueue_head(&(dev->user_wait_queue));
     init_waitqueue_head(&(dev->host_wait_queue));
 
-    INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
-    
     // Insert ourselves into the list
-    spin_lock_irqsave(&(host_dev->lock),f1);
+    spin_lock_irqsave(&(host_dev->lock),f);
     list_add(&(dev->node),&(host_dev->devs));
-    spin_unlock_irqrestore(&(host_dev->lock),f1);
+    spin_unlock_irqrestore(&(host_dev->lock),f);
+
+    INFO("palacios: host device \"%s\" created with deferred rendezvous\n",url);
+
+    return dev;
 
-    
-    // Now wait until we are noticed!
-    for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) { 
-       spin_lock_irqsave(&(dev->lock),f2);
-       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),f2);
-           return dev;
-       }
-       spin_unlock_irqrestore(&(dev->lock),f2);
-       ssleep(RENDEZVOUS_RETRY_SECS);
-    }
-    
-    ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
-    
-    // get us out of the list
-    spin_lock_irqsave(&(host_dev->lock),f1);
-    list_del(&(dev->node));
-    spin_unlock_irqrestore(&(host_dev->lock),f1);
-    
-    palacios_host_dev_user_free(dev);
-    
-    return NULL;
 }
 
+
+
 static int palacios_host_dev_close(v3_host_dev_t hostdev)
 {
     unsigned long f1, f2;
@@ -803,7 +824,7 @@ static int palacios_host_dev_close(v3_host_dev_t hostdev)
        return -1;
     }
 
-    host_dev = get_vm_ext_data(dev->guest, "HOST_DEV_INTERFACE");
+    host_dev = get_vm_ext_data(dev->guest, "HOST_DEVICE_INTERFACE");
 
     
     if (host_dev == NULL) {
@@ -846,17 +867,18 @@ static uint64_t palacios_host_dev_read_io(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
+
     
     
     // resize request (no data)
@@ -920,14 +942,15 @@ static uint64_t palacios_host_dev_read_mem(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
     
@@ -991,14 +1014,15 @@ static uint64_t palacios_host_dev_read_conf(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
     
@@ -1063,14 +1087,15 @@ static uint64_t palacios_host_dev_write_io(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
 
@@ -1135,14 +1160,15 @@ static uint64_t palacios_host_dev_write_mem(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
     
@@ -1209,14 +1235,15 @@ static uint64_t palacios_host_dev_write_conf(v3_host_dev_t hostdev,
 
     spin_lock_irqsave(&(dev->lock),f);
     
-    if (dev->waiting) { 
+    if (palacios_host_dev_rendezvous(dev)) {
        spin_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);
+       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->connected) {
+
+    if (dev->waiting) { 
        spin_unlock_irqrestore(&(dev->lock),f);
-       ERROR("palacios: ignoring request as user side is not connected for host device \"%s\"\n",dev->url);
+       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;
     }
     
@@ -1279,7 +1306,7 @@ static int palacios_host_dev_ack_irq(v3_host_dev_t hostdev, uint8_t irq)
 
 
 static struct v3_host_dev_hooks palacios_host_dev_hooks = {
-    .open                      = palacios_host_dev_open,
+    .open                      = palacios_host_dev_open_deferred,
     .close                      = palacios_host_dev_close,
     .read_io                    = palacios_host_dev_read_io,
     .write_io                   = palacios_host_dev_write_io,
@@ -1319,7 +1346,7 @@ static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
 
 
 static struct linux_ext host_dev_ext = {
-    .name = "HOST_DEV_INTERFACE",
+    .name = "HOST_DEVICE_INTERFACE",
     .init = host_dev_init,
     .deinit = NULL,
     .guest_init = host_dev_guest_init,