9119d9
From c9aea427cc39190d178c584548b71e099a66df71 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <c9aea427cc39190d178c584548b71e099a66df71@dist-git>
9119d9
From: Martin Kletzander <mkletzan@redhat.com>
9119d9
Date: Fri, 3 Oct 2014 22:54:55 +0200
9119d9
Subject: [PATCH] docs, conf, schema: add support for shmem device
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1126991
9119d9
9119d9
This patch adds parsing/formatting code as well as documentation for
9119d9
shared memory devices.  This will currently be only accessible in QEMU
9119d9
using it's ivshmem device, but is designed as generic as possible to
9119d9
allow future expansion for other hypervisors.
9119d9
9119d9
In the devices section in the domain XML users may specify:
9119d9
9119d9
- For shmem device using a server:
9119d9
9119d9
 <shmem name='shmem0'>
9119d9
   <server path='/tmp/socket-ivshmem0'/>
9119d9
   <size unit='M'>32</size>
9119d9
   <msi vectors='32' ioeventfd='on'/>
9119d9
 </shmem>
9119d9
9119d9
- For ivshmem device not using an ivshmem server:
9119d9
9119d9
 <shmem name='shmem1'>
9119d9
   <size unit='M'>32</size>
9119d9
 </shmem>
9119d9
9119d9
Most of the configuration is made optional so it also allows
9119d9
specifications like:
9119d9
9119d9
 
9119d9
 <shmem name='shmem2'>
9119d9
   <server/>
9119d9
 </shmem>
9119d9
9119d9
Signed-off-by: Maxime Leroy <maxime.leroy@6wind.com>
9119d9
Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
9119d9
(cherry picked from commit 540a84ec89c1634d5e17ba7b8d96049c960bb1b4)
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 docs/formatdomain.html.in                          |  52 ++++++
9119d9
 docs/schemas/domaincommon.rng                      |  39 +++++
9119d9
 src/conf/domain_conf.c                             | 184 ++++++++++++++++++++-
9119d9
 src/conf/domain_conf.h                             |  24 +++
9119d9
 src/qemu/qemu_hotplug.c                            |   1 +
9119d9
 .../qemuxml2argv-shmem-msi-only.xml                |  24 +++
9119d9
 tests/qemuxml2argvdata/qemuxml2argv-shmem.xml      |  51 ++++++
9119d9
 tests/qemuxml2argvtest.c                           |   2 +
9119d9
 tests/qemuxml2xmltest.c                            |   1 +
9119d9
 9 files changed, 377 insertions(+), 1 deletion(-)
9119d9
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem-msi-only.xml
9119d9
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-shmem.xml
9119d9
9119d9
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
9119d9
index ee00eca..dac81ab 100644
9119d9
--- a/docs/formatdomain.html.in
9119d9
+++ b/docs/formatdomain.html.in
9119d9
@@ -5582,6 +5582,58 @@ qemu-kvm -net nic,model=? /dev/null
9119d9
     
9119d9
   
9119d9
 
9119d9
+  

Shared memory device

9119d9
+
9119d9
+    

9119d9
+      A shared memory device allows to share a memory region between
9119d9
+      different virtual machines and the host.
9119d9
+      Since 1.2.9, QEMU and KVM only
9119d9
+    

9119d9
+
9119d9
+
9119d9
+  ...
9119d9
+  <devices>
9119d9
+    <shmem name='my_shmem0'>
9119d9
+      <size unit='M'>4</size>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem_server'>
9119d9
+      <size unit='M'>2</size>
9119d9
+      <server path='/tmp/socket-shmem'/>
9119d9
+      <msi vectors='32' ioeventfd='on'/>
9119d9
+    </shmem>
9119d9
+  </devices>
9119d9
+  ...
9119d9
+
9119d9
+
9119d9
+  
9119d9
+    
shmem
9119d9
+    
9119d9
+      The shmem element has one mandatory attribute,
9119d9
+      name to identify the shared memory.
9119d9
+    
9119d9
+    
size
9119d9
+    
9119d9
+      The optional size element specifies the size of the shared
9119d9
+      memory. This must be power of 2 and greater than or equal to 1 MiB.
9119d9
+    
9119d9
+    
server
9119d9
+    
9119d9
+      The optional server element can be used to configure a server
9119d9
+      socket the device is supposed to connect to.  The optional
9119d9
+      path attribute specifies the path to the unix socket and
9119d9
+      defaults to /var/lib/libvirt/shmem/$shmem-$name-sock.
9119d9
+    
9119d9
+    
msi
9119d9
+    
9119d9
+      The optional msi element enables/disables (values "on"/"off",
9119d9
+      respectively) MSI interrupts. This option can currently be used only
9119d9
+      together with the server element. The vectors
9119d9
+      attribute can be used to specify the number of interrupt
9119d9
+      vectors. The ioeventd attribute enables/disables (values
9119d9
+      "on"/"off", respectively) ioeventfd.
9119d9
+    
9119d9
+  
9119d9
+
9119d9
     

Security label

9119d9
 
9119d9
     

9119d9
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
9119d9
index e561486..8d96daa 100644
9119d9
--- a/docs/schemas/domaincommon.rng
9119d9
+++ b/docs/schemas/domaincommon.rng
9119d9
@@ -3274,6 +3274,44 @@
9119d9
       </optional>
9119d9
     </element>
9119d9
   </define>
9119d9
+
9119d9
+  <define name="shmem">
9119d9
+    <element name="shmem">
9119d9
+      <attribute name="name"/>
9119d9
+      <interleave>
9119d9
+        <optional>
9119d9
+          <element name="size">
9119d9
+            <ref name="scaledInteger"/>
9119d9
+          </element>
9119d9
+        </optional>
9119d9
+        <optional>
9119d9
+          <element name="server">
9119d9
+            <optional>
9119d9
+              <attribute name="path">
9119d9
+                <ref name="absFilePath"/>
9119d9
+              </attribute>
9119d9
+            </optional>
9119d9
+          </element>
9119d9
+        </optional>
9119d9
+        <optional>
9119d9
+          <element name="msi">
9119d9
+            <optional>
9119d9
+              <ref name="ioeventfd"/>
9119d9
+            </optional>
9119d9
+            <optional>
9119d9
+              <attribute name="vectors">
9119d9
+                <ref name="unsignedInt"/>
9119d9
+              </attribute>
9119d9
+            </optional>
9119d9
+          </element>
9119d9
+        </optional>
9119d9
+        <optional>
9119d9
+          <ref name="address"/>
9119d9
+        </optional>
9119d9
+      </interleave>
9119d9
+    </element>
9119d9
+  </define>
9119d9
+
9119d9
   <define name="memballoon">
9119d9
     <element name="memballoon">
9119d9
       <attribute name="model">
9119d9
@@ -3860,6 +3898,7 @@
9119d9
             <ref name="redirfilter"/>
9119d9
             <ref name="rng"/>
9119d9
             <ref name="tpm"/>
9119d9
+            <ref name="shmem"/>
9119d9
           </choice>
9119d9
         </zeroOrMore>
9119d9
         <optional>
9119d9
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
9119d9
index 40626b8..2768660 100644
9119d9
--- a/src/conf/domain_conf.c
9119d9
+++ b/src/conf/domain_conf.c
9119d9
@@ -252,7 +252,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
9119d9
               "chr",
9119d9
               "memballoon",
9119d9
               "nvram",
9119d9
-              "rng")
9119d9
+              "rng",
9119d9
+              "shmem")
9119d9
 
9119d9
 VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
9119d9
               "none",
9119d9
@@ -1717,6 +1718,17 @@ void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def)
9119d9
     VIR_FREE(def);
9119d9
 }
9119d9
 
9119d9
+void virDomainShmemDefFree(virDomainShmemDefPtr def)
9119d9
+{
9119d9
+    if (!def)
9119d9
+        return;
9119d9
+
9119d9
+    virDomainDeviceInfoClear(&def->info);
9119d9
+    VIR_FREE(def->server.path);
9119d9
+    VIR_FREE(def->name);
9119d9
+    VIR_FREE(def);
9119d9
+}
9119d9
+
9119d9
 void virDomainVideoDefFree(virDomainVideoDefPtr def)
9119d9
 {
9119d9
     if (!def)
9119d9
@@ -1918,6 +1930,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
9119d9
     case VIR_DOMAIN_DEVICE_NVRAM:
9119d9
         virDomainNVRAMDefFree(def->data.nvram);
9119d9
         break;
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
+        virDomainShmemDefFree(def->data.shmem);
9119d9
+        break;
9119d9
     case VIR_DOMAIN_DEVICE_LAST:
9119d9
     case VIR_DOMAIN_DEVICE_NONE:
9119d9
         break;
9119d9
@@ -2178,6 +2193,10 @@ void virDomainDefFree(virDomainDefPtr def)
9119d9
 
9119d9
     virDomainRedirFilterDefFree(def->redirfilter);
9119d9
 
9119d9
+    for (i = 0; i < def->nshmems; i++)
9119d9
+        virDomainShmemDefFree(def->shmems[i]);
9119d9
+    VIR_FREE(def->shmems);
9119d9
+
9119d9
     if (def->namespaceData && def->ns.free)
9119d9
         (def->ns.free)(def->namespaceData);
9119d9
 
9119d9
@@ -2610,6 +2629,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
9119d9
         return &device->data.memballoon->info;
9119d9
     case VIR_DOMAIN_DEVICE_NVRAM:
9119d9
         return &device->data.nvram->info;
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
+        return &device->data.shmem->info;
9119d9
     case VIR_DOMAIN_DEVICE_RNG:
9119d9
         return &device->data.rng->info;
9119d9
 
9119d9
@@ -2825,6 +2846,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
9119d9
         if (cb(def, &device, &def->hubs[i]->info, opaque) < 0)
9119d9
             return -1;
9119d9
     }
9119d9
+    device.type = VIR_DOMAIN_DEVICE_SHMEM;
9119d9
+    for (i = 0; i < def->nshmems; i++) {
9119d9
+        device.data.shmem = def->shmems[i];
9119d9
+        if (cb(def, &device, &def->shmems[i]->info, opaque) < 0)
9119d9
+            return -1;
9119d9
+    }
9119d9
 
9119d9
     /* Coverity is not very happy with this - all dead_error_condition */
9119d9
 #if !STATIC_ANALYSIS
9119d9
@@ -2853,6 +2880,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
9119d9
     case VIR_DOMAIN_DEVICE_CHR:
9119d9
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
9119d9
     case VIR_DOMAIN_DEVICE_NVRAM:
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
     case VIR_DOMAIN_DEVICE_LAST:
9119d9
     case VIR_DOMAIN_DEVICE_RNG:
9119d9
         break;
9119d9
@@ -9687,6 +9715,84 @@ virDomainNVRAMDefParseXML(xmlNodePtr node,
9119d9
     return NULL;
9119d9
 }
9119d9
 
9119d9
+static virDomainShmemDefPtr
9119d9
+virDomainShmemDefParseXML(xmlNodePtr node,
9119d9
+                          xmlXPathContextPtr ctxt,
9119d9
+                          unsigned int flags)
9119d9
+{
9119d9
+    char *tmp = NULL;
9119d9
+    virDomainShmemDefPtr def = NULL;
9119d9
+    virDomainShmemDefPtr ret = NULL;
9119d9
+    xmlNodePtr msi = NULL;
9119d9
+    xmlNodePtr save = ctxt->node;
9119d9
+    xmlNodePtr server = NULL;
9119d9
+
9119d9
+
9119d9
+    if (VIR_ALLOC(def) < 0)
9119d9
+        return NULL;
9119d9
+
9119d9
+    ctxt->node = node;
9119d9
+
9119d9
+    if (!(def->name = virXMLPropString(node, "name"))) {
9119d9
+        virReportError(VIR_ERR_XML_ERROR, "%s",
9119d9
+                       _("shmem element must contain 'name' attribute"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if (virDomainParseScaledValue("./size[1]", ctxt, &def->size,
9119d9
+                                    1, ULLONG_MAX, false) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if ((server = virXPathNode("./server", ctxt))) {
9119d9
+        def->server.enabled = true;
9119d9
+
9119d9
+        if ((tmp = virXMLPropString(server, "path")))
9119d9
+            def->server.path = virFileSanitizePath(tmp);
9119d9
+        VIR_FREE(tmp);
9119d9
+    }
9119d9
+
9119d9
+    if ((msi = virXPathNode("./msi", ctxt))) {
9119d9
+        def->msi.enabled = true;
9119d9
+
9119d9
+        if ((tmp = virXMLPropString(msi, "vectors")) &&
9119d9
+            virStrToLong_uip(tmp, NULL, 0, &def->msi.vectors) < 0) {
9119d9
+            virReportError(VIR_ERR_XML_ERROR,
9119d9
+                           _("invalid number of vectors for shmem: '%s'"),
9119d9
+                           tmp);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+        VIR_FREE(tmp);
9119d9
+
9119d9
+        if ((tmp = virXMLPropString(msi, "ioeventfd")) &&
9119d9
+            (def->msi.ioeventfd = virTristateSwitchTypeFromString(tmp)) <= 0) {
9119d9
+            virReportError(VIR_ERR_XML_ERROR,
9119d9
+                           _("invalid msi ioeventfd setting for shmem: '%s'"),
9119d9
+                           tmp);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+        VIR_FREE(tmp);
9119d9
+    }
9119d9
+
9119d9
+    /* msi option is only relevant with a server */
9119d9
+    if (def->msi.enabled && !def->server.enabled) {
9119d9
+        virReportError(VIR_ERR_XML_ERROR, "%s",
9119d9
+                       _("msi option is only supported with a server"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+
9119d9
+    ret = def;
9119d9
+    def = NULL;
9119d9
+ cleanup:
9119d9
+    ctxt->node = save;
9119d9
+    VIR_FREE(tmp);
9119d9
+    virDomainShmemDefFree(def);
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
 static virSysinfoDefPtr
9119d9
 virSysinfoParseXML(xmlNodePtr node,
9119d9
                   xmlXPathContextPtr ctxt,
9119d9
@@ -10543,6 +10649,10 @@ virDomainDeviceDefParse(const char *xmlStr,
9119d9
         if (!(dev->data.nvram = virDomainNVRAMDefParseXML(node, flags)))
9119d9
             goto error;
9119d9
         break;
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
+        if (!(dev->data.shmem = virDomainShmemDefParseXML(node, ctxt, flags)))
9119d9
+            goto error;
9119d9
+        break;
9119d9
     case VIR_DOMAIN_DEVICE_NONE:
9119d9
     case VIR_DOMAIN_DEVICE_LAST:
9119d9
         break;
9119d9
@@ -13630,6 +13740,25 @@ virDomainDefParseXML(xmlDocPtr xml,
9119d9
         VIR_FREE(nodes);
9119d9
     }
9119d9
 
9119d9
+    /* analysis of the shmem devices */
9119d9
+    if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0) {
9119d9
+        goto error;
9119d9
+    }
9119d9
+    if (n && VIR_ALLOC_N(def->shmems, n) < 0)
9119d9
+        goto error;
9119d9
+
9119d9
+    node = ctxt->node;
9119d9
+    for (i = 0; i < n; i++) {
9119d9
+        virDomainShmemDefPtr shmem;
9119d9
+        ctxt->node = nodes[i];
9119d9
+        shmem = virDomainShmemDefParseXML(nodes[i], ctxt, flags);
9119d9
+        if (!shmem)
9119d9
+            goto error;
9119d9
+
9119d9
+        def->shmems[def->nshmems++] = shmem;
9119d9
+    }
9119d9
+    ctxt->node = node;
9119d9
+    VIR_FREE(nodes);
9119d9
 
9119d9
     /* analysis of the user namespace mapping */
9119d9
     if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
9119d9
@@ -17419,6 +17548,54 @@ static int virDomainPanicDefFormat(virBufferPtr buf,
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
+virDomainShmemDefFormat(virBufferPtr buf,
9119d9
+                        virDomainShmemDefPtr def,
9119d9
+                        unsigned int flags)
9119d9
+{
9119d9
+    virBufferAsprintf(buf, "<shmem name='%s'", def->name);
9119d9
+
9119d9
+    if (!def->size &&
9119d9
+        !def->server.enabled &&
9119d9
+        !def->msi.enabled &&
9119d9
+        !virDomainDeviceInfoIsSet(&def->info, flags)) {
9119d9
+        virBufferAddLit(buf, "/>\n");
9119d9
+        return 0;
9119d9
+    } else {
9119d9
+        virBufferAddLit(buf, ">\n");
9119d9
+    }
9119d9
+
9119d9
+    virBufferAdjustIndent(buf, 2);
9119d9
+
9119d9
+    if (def->size)
9119d9
+        virBufferAsprintf(buf, "<size unit='M'>%llu</size>\n",
9119d9
+                          VIR_DIV_UP(def->size, 1024 * 1024));
9119d9
+
9119d9
+    if (def->server.enabled) {
9119d9
+        virBufferAddLit(buf, "
9119d9
+        virBufferEscapeString(buf, " path='%s'", def->server.path);
9119d9
+        virBufferAddLit(buf, "/>\n");
9119d9
+    }
9119d9
+
9119d9
+    if (def->msi.enabled) {
9119d9
+        virBufferAddLit(buf, "
9119d9
+        if (def->msi.vectors)
9119d9
+            virBufferAsprintf(buf, " vectors='%u'", def->msi.vectors);
9119d9
+        if (def->msi.ioeventfd)
9119d9
+            virBufferAsprintf(buf, " ioeventfd='%s'",
9119d9
+                              virTristateSwitchTypeToString(def->msi.ioeventfd));
9119d9
+        virBufferAddLit(buf, "/>\n");
9119d9
+    }
9119d9
+
9119d9
+    if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
9119d9
+        return -1;
9119d9
+
9119d9
+    virBufferAdjustIndent(buf, -2);
9119d9
+    virBufferAddLit(buf, "</shmem>\n");
9119d9
+
9119d9
+    return 0;
9119d9
+}
9119d9
+
9119d9
+static int
9119d9
 virDomainRNGDefFormat(virBufferPtr buf,
9119d9
                       virDomainRNGDefPtr def,
9119d9
                       unsigned int flags)
9119d9
@@ -19038,6 +19215,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
9119d9
         virDomainPanicDefFormat(buf, def->panic) < 0)
9119d9
         goto error;
9119d9
 
9119d9
+    for (n = 0; n < def->nshmems; n++)
9119d9
+        if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
9119d9
+            goto error;
9119d9
+
9119d9
     virBufferAdjustIndent(buf, -2);
9119d9
     virBufferAddLit(buf, "</devices>\n");
9119d9
 
9119d9
@@ -20403,6 +20584,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
9119d9
     case VIR_DOMAIN_DEVICE_SMARTCARD:
9119d9
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
9119d9
     case VIR_DOMAIN_DEVICE_NVRAM:
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
     case VIR_DOMAIN_DEVICE_LAST:
9119d9
         virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
                        _("Copying definition of '%d' type "
9119d9
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
9119d9
index b981020..9da6d2d 100644
9119d9
--- a/src/conf/domain_conf.h
9119d9
+++ b/src/conf/domain_conf.h
9119d9
@@ -136,6 +136,9 @@ typedef virDomainPanicDef *virDomainPanicDefPtr;
9119d9
 typedef struct _virDomainChrSourceDef virDomainChrSourceDef;
9119d9
 typedef virDomainChrSourceDef *virDomainChrSourceDefPtr;
9119d9
 
9119d9
+typedef struct _virDomainShmemDef virDomainShmemDef;
9119d9
+typedef virDomainShmemDef *virDomainShmemDefPtr;
9119d9
+
9119d9
 /* Flags for the 'type' field in virDomainDeviceDef */
9119d9
 typedef enum {
9119d9
     VIR_DOMAIN_DEVICE_NONE = 0,
9119d9
@@ -157,6 +160,7 @@ typedef enum {
9119d9
     VIR_DOMAIN_DEVICE_MEMBALLOON,
9119d9
     VIR_DOMAIN_DEVICE_NVRAM,
9119d9
     VIR_DOMAIN_DEVICE_RNG,
9119d9
+    VIR_DOMAIN_DEVICE_SHMEM,
9119d9
 
9119d9
     VIR_DOMAIN_DEVICE_LAST
9119d9
 } virDomainDeviceType;
9119d9
@@ -184,6 +188,7 @@ struct _virDomainDeviceDef {
9119d9
         virDomainMemballoonDefPtr memballoon;
9119d9
         virDomainNVRAMDefPtr nvram;
9119d9
         virDomainRNGDefPtr rng;
9119d9
+        virDomainShmemDefPtr shmem;
9119d9
     } data;
9119d9
 };
9119d9
 
9119d9
@@ -1507,6 +1512,21 @@ struct _virDomainNVRAMDef {
9119d9
     virDomainDeviceInfo info;
9119d9
 };
9119d9
 
9119d9
+struct _virDomainShmemDef {
9119d9
+    char *name;
9119d9
+    unsigned long long size;
9119d9
+    struct {
9119d9
+        bool enabled;
9119d9
+        char *path;
9119d9
+    } server;
9119d9
+    struct {
9119d9
+        bool enabled;
9119d9
+        unsigned vectors;
9119d9
+        virTristateSwitch ioeventfd;
9119d9
+    } msi;
9119d9
+    virDomainDeviceInfo info;
9119d9
+};
9119d9
+
9119d9
 typedef enum {
9119d9
     VIR_DOMAIN_SMBIOS_NONE = 0,
9119d9
     VIR_DOMAIN_SMBIOS_EMULATE,
9119d9
@@ -2063,6 +2083,9 @@ struct _virDomainDef {
9119d9
     size_t nrngs;
9119d9
     virDomainRNGDefPtr *rngs;
9119d9
 
9119d9
+    size_t nshmems;
9119d9
+    virDomainShmemDefPtr *shmems;
9119d9
+
9119d9
     /* Only 1 */
9119d9
     virDomainWatchdogDefPtr watchdog;
9119d9
     virDomainMemballoonDefPtr memballoon;
9119d9
@@ -2260,6 +2283,7 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
9119d9
 void virDomainHubDefFree(virDomainHubDefPtr def);
9119d9
 void virDomainRedirdevDefFree(virDomainRedirdevDefPtr def);
9119d9
 void virDomainRedirFilterDefFree(virDomainRedirFilterDefPtr def);
9119d9
+void virDomainShmemDefFree(virDomainShmemDefPtr def);
9119d9
 void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
9119d9
 virDomainDeviceDefPtr virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
9119d9
                                              const virDomainDef *def,
9119d9
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
9119d9
index 33e2dff..8eb2419 100644
9119d9
--- a/src/qemu/qemu_hotplug.c
9119d9
+++ b/src/qemu/qemu_hotplug.c
9119d9
@@ -2858,6 +2858,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
9119d9
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
9119d9
     case VIR_DOMAIN_DEVICE_NVRAM:
9119d9
     case VIR_DOMAIN_DEVICE_RNG:
9119d9
+    case VIR_DOMAIN_DEVICE_SHMEM:
9119d9
     case VIR_DOMAIN_DEVICE_LAST:
9119d9
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
9119d9
                        _("don't know how to remove a %s device"),
9119d9
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-shmem-msi-only.xml b/tests/qemuxml2argvdata/qemuxml2argv-shmem-msi-only.xml
9119d9
new file mode 100644
9119d9
index 0000000..d70279c
9119d9
--- /dev/null
9119d9
+++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem-msi-only.xml
9119d9
@@ -0,0 +1,24 @@
9119d9
+<domain type='qemu'>
9119d9
+  <name>QEMUGuest1</name>
9119d9
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
9119d9
+  <memory unit='KiB'>219136</memory>
9119d9
+  <currentMemory unit='KiB'>219136</currentMemory>
9119d9
+  <vcpu placement='static'>1</vcpu>
9119d9
+  <os>
9119d9
+    <type arch='i686' machine='pc'>hvm</type>
9119d9
+    <boot dev='hd'/>
9119d9
+  </os>
9119d9
+  <clock offset='utc'/>
9119d9
+  <on_poweroff>destroy</on_poweroff>
9119d9
+  <on_reboot>restart</on_reboot>
9119d9
+  <on_crash>destroy</on_crash>
9119d9
+  <devices>
9119d9
+    <emulator>/usr/bin/qemu</emulator>
9119d9
+    <controller type='usb' index='0'/>
9119d9
+    <controller type='pci' index='0' model='pci-root'/>
9119d9
+    <memballoon model='none'/>
9119d9
+    <shmem name='shmem0'>
9119d9
+      <msi/>
9119d9
+    </shmem>
9119d9
+  </devices>
9119d9
+</domain>
9119d9
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-shmem.xml b/tests/qemuxml2argvdata/qemuxml2argv-shmem.xml
9119d9
new file mode 100644
9119d9
index 0000000..fd79c89
9119d9
--- /dev/null
9119d9
+++ b/tests/qemuxml2argvdata/qemuxml2argv-shmem.xml
9119d9
@@ -0,0 +1,51 @@
9119d9
+<domain type='qemu'>
9119d9
+  <name>QEMUGuest1</name>
9119d9
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
9119d9
+  <memory unit='KiB'>219136</memory>
9119d9
+  <currentMemory unit='KiB'>219136</currentMemory>
9119d9
+  <vcpu placement='static'>1</vcpu>
9119d9
+  <os>
9119d9
+    <type arch='i686' machine='pc'>hvm</type>
9119d9
+    <boot dev='hd'/>
9119d9
+  </os>
9119d9
+  <clock offset='utc'/>
9119d9
+  <on_poweroff>destroy</on_poweroff>
9119d9
+  <on_reboot>restart</on_reboot>
9119d9
+  <on_crash>destroy</on_crash>
9119d9
+  <devices>
9119d9
+    <emulator>/usr/bin/qemu</emulator>
9119d9
+    <controller type='usb' index='0'/>
9119d9
+    <controller type='pci' index='0' model='pci-root'/>
9119d9
+    <memballoon model='none'/>
9119d9
+    <shmem name='shmem0'/>
9119d9
+    <shmem name='shmem1'>
9119d9
+      <size unit='M'>128</size>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem2'>
9119d9
+      <size unit='M'>256</size>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem3'>
9119d9
+      <size unit='M'>512</size>
9119d9
+      <server/>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem4'>
9119d9
+      <size unit='M'>1024</size>
9119d9
+      <server path='/tmp/shmem4-sock'/>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem5'>
9119d9
+      <size unit='M'>2048</size>
9119d9
+      <server path='/tmp/shmem5-sock'/>
9119d9
+      <msi ioeventfd='off'/>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem6'>
9119d9
+      <size unit='M'>4096</size>
9119d9
+      <server path='/tmp/shmem6-sock'/>
9119d9
+      <msi vectors='16'/>
9119d9
+    </shmem>
9119d9
+    <shmem name='shmem7'>
9119d9
+      <size unit='M'>8192</size>
9119d9
+      <server path='/tmp/shmem7-sock'/>
9119d9
+      <msi vectors='32' ioeventfd='on'/>
9119d9
+    </shmem>
9119d9
+  </devices>
9119d9
+</domain>
9119d9
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
9119d9
index 410540f..ae8bbfc 100644
9119d9
--- a/tests/qemuxml2argvtest.c
9119d9
+++ b/tests/qemuxml2argvtest.c
9119d9
@@ -1463,6 +1463,8 @@ mymain(void)
9119d9
 
9119d9
     DO_TEST("fips-enabled", QEMU_CAPS_ENABLE_FIPS);
9119d9
 
9119d9
+    DO_TEST_PARSE_ERROR("shmem-msi-only", NONE);
9119d9
+
9119d9
     virObjectUnref(driver.config);
9119d9
     virObjectUnref(driver.caps);
9119d9
     virObjectUnref(driver.xmlopt);
9119d9
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
9119d9
index 6e71cb2..f29e4ed 100644
9119d9
--- a/tests/qemuxml2xmltest.c
9119d9
+++ b/tests/qemuxml2xmltest.c
9119d9
@@ -403,6 +403,7 @@ mymain(void)
9119d9
     DO_TEST("bios-nvram");
9119d9
 
9119d9
     DO_TEST("tap-vhost");
9119d9
+    DO_TEST("shmem");
9119d9
 
9119d9
     virObjectUnref(driver.caps);
9119d9
     virObjectUnref(driver.xmlopt);
9119d9
-- 
9119d9
2.1.2
9119d9