This patch adds configuration support for the shmem device
as described in the schema in the previous patch.
Signed-off-by: Maxime Leroy <maxime.leroy(a)6wind.com>
---
src/conf/domain_conf.c | 249 ++++++++++++++++++++++++++++++++++++++++++++++-
src/conf/domain_conf.h | 41 ++++++++
src/libvirt_private.syms | 2 +
3 files changed, 291 insertions(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9557020..08d653a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -234,7 +234,8 @@ VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
"chr",
"memballoon",
"nvram",
- "rng")
+ "rng",
+ "shmem")
VIR_ENUM_IMPL(virDomainDeviceAddress, VIR_DOMAIN_DEVICE_ADDRESS_TYPE_LAST,
"none",
@@ -759,6 +760,9 @@ VIR_ENUM_IMPL(virDomainDiskMirrorState,
VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
"abort",
"pivot")
+VIR_ENUM_IMPL(virDomainShmemModel, VIR_DOMAIN_SHMEM_MODEL_LAST,
+ "ivshmem")
+
/* Internal mapping: subset of block job types that can be present in
* <mirror> XML (remaining types are not two-phase). */
VIR_ENUM_DECL(virDomainBlockJob)
@@ -1692,6 +1696,26 @@ void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def)
VIR_FREE(def);
}
+void virDomainShmemDefFree(virDomainShmemDefPtr def)
+{
+ if (!def)
+ return;
+
+ switch (def->model) {
+ case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
+ VIR_FREE(def->data.ivshmem.server.path);
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected shmem model %d"), def->model);
+ }
+
+ virDomainDeviceInfoClear(&def->info);
+
+ VIR_FREE(def->name);
+ VIR_FREE(def);
+}
+
void virDomainVideoDefFree(virDomainVideoDefPtr def)
{
if (!def)
@@ -1893,6 +1917,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
case VIR_DOMAIN_DEVICE_NVRAM:
virDomainNVRAMDefFree(def->data.nvram);
break;
+ case VIR_DOMAIN_DEVICE_SHMEM:
+ virDomainShmemDefFree(def->data.shmem);
+ break;
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_NONE:
break;
@@ -2134,6 +2161,10 @@ void virDomainDefFree(virDomainDefPtr def)
virDomainRedirFilterDefFree(def->redirfilter);
+ for (i = 0; i < def->nshmems; i++)
+ virDomainShmemDefFree(def->shmems[i]);
+ VIR_FREE(def->shmems);
+
if (def->namespaceData && def->ns.free)
(def->ns.free)(def->namespaceData);
@@ -2568,6 +2599,8 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
return &device->data.memballoon->info;
case VIR_DOMAIN_DEVICE_NVRAM:
return &device->data.nvram->info;
+ case VIR_DOMAIN_DEVICE_SHMEM:
+ return &device->data.shmem->info;
case VIR_DOMAIN_DEVICE_RNG:
return &device->data.rng->info;
@@ -2783,6 +2816,12 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
if (cb(def, &device, &def->hubs[i]->info, opaque) < 0)
return -1;
}
+ device.type = VIR_DOMAIN_DEVICE_SHMEM;
+ for (i = 0; i < def->nshmems; i++) {
+ device.data.shmem = def->shmems[i];
+ if (cb(def, &device, &def->shmems[i]->info, opaque) < 0)
+ return -1;
+ }
/* This switch statement is here to trigger compiler warning when adding
* a new device type. When you are adding a new field to the switch you
@@ -2809,6 +2848,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
case VIR_DOMAIN_DEVICE_CHR:
case VIR_DOMAIN_DEVICE_MEMBALLOON:
case VIR_DOMAIN_DEVICE_NVRAM:
+ case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_LAST:
case VIR_DOMAIN_DEVICE_RNG:
break;
@@ -9462,6 +9502,135 @@ virDomainNVRAMDefParseXML(xmlNodePtr node,
return NULL;
}
+static int
+virDomainIvshmemDefParseXML(xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ virDomainIvshmemDefPtr def)
+{
+ char *ioeventfd = NULL;
+ char *vectors = NULL;
+ xmlNodePtr cur;
+ xmlNodePtr save = ctxt->node;
+ int ret;
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "server")) {
+ def->server.enabled = true;
+ if (!(def->server.path = virXMLPropString(cur, "path"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse <server> 'path'
attribute"));
+ goto error;
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "size")) {
+ if (virDomainParseScaledValue("./size[1]", ctxt,
+ &def->size, 1,
+ ULLONG_MAX, true) < 0) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("cannot parse <size> attribute"));
+ goto error;
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "msi")) {
+ def->msi.enabled = true;
+ vectors = virXMLPropString(cur, "vectors");
+ ioeventfd = virXMLPropString(cur, "ioeventfd");
+
+ if (vectors &&
+ virStrToLong_ui(vectors, NULL, 10, &def->msi.vectors) < 0)
{
+ virReportError(VIR_ERR_XML_ERROR,
+ _("cannot parse <msi> 'vectors'
attribute '%s'"),
+ vectors);
+ goto error;
+ }
+ if (ioeventfd &&
+ (def->msi.ioeventfd =
+ virTristateSwitchTypeFromString(ioeventfd)) <= 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("cannot parse <msi> 'ioeventfd'
mode '%s'"),
+ ioeventfd);
+ goto error;
+ }
+ }
+ }
+ cur = cur->next;
+ }
+
+ /* msi option is only relevant with a server */
+ if (def->msi.enabled && !def->server.enabled) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("msi option is only supported with an ivshmem
server"));
+ goto error;
+ }
+
+ /* size should be a power of two */
+ if (def->size & (def->size-1)) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("shmem size should be a power of two for ivshmem
model"));
+ goto error;
+ }
+
+ ret = 0;
+ cleanup:
+ ctxt->node = save;
+ VIR_FREE(ioeventfd);
+ VIR_FREE(vectors);
+ return ret;
+
+ error:
+ ret = -1;
+ goto cleanup;
+}
+
+static virDomainShmemDefPtr
+virDomainShmemDefParseXML(xmlNodePtr node,
+ xmlXPathContextPtr ctxt,
+ unsigned int flags)
+{
+ char *model = virXMLPropString(node, "model");
+ virDomainShmemDefPtr def;
+
+ if (VIR_ALLOC(def) < 0)
+ return NULL;
+
+ if (model) {
+ if ((def->model == virDomainShmemModelTypeFromString(model)) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Unknown <shmem> model '%s'"),
model);
+ goto error;
+ }
+ } else
+ def->model = VIR_DOMAIN_SHMEM_MODEL_IVSHMEM;
+
+ if (!(def->name = virXMLPropString(node, "name"))) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("<shmem> must contain 'name'
attribute"));
+ goto error;
+ }
+
+ switch (def->model) {
+ case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
+ if (virDomainIvshmemDefParseXML(node, ctxt, &def->data.ivshmem) < 0)
+ goto error;
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected <shmem> model %d"), def->model);
+ goto error;
+ }
+
+ if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
+ goto error;
+
+ cleanup:
+ VIR_FREE(model);
+ return def;
+ error:
+ virDomainShmemDefFree(def);
+ def = NULL;
+ goto cleanup;
+}
+
static virSysinfoDefPtr
virSysinfoParseXML(xmlNodePtr node,
xmlXPathContextPtr ctxt,
@@ -10318,6 +10487,10 @@ virDomainDeviceDefParse(const char *xmlStr,
if (!(dev->data.nvram = virDomainNVRAMDefParseXML(node, flags)))
goto error;
break;
+ case VIR_DOMAIN_DEVICE_SHMEM:
+ if (!(dev->data.shmem = virDomainShmemDefParseXML(node, ctxt, flags)))
+ goto error;
+ break;
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LAST:
break;
@@ -13200,6 +13373,25 @@ virDomainDefParseXML(xmlDocPtr xml,
VIR_FREE(nodes);
}
+ /* analysis of the shmem devices */
+ if ((n = virXPathNodeSet("./devices/shmem", ctxt, &nodes)) < 0) {
+ goto error;
+ }
+ if (n && VIR_ALLOC_N(def->shmems, n) < 0)
+ goto error;
+
+ node = ctxt->node;
+ for (i = 0; i < n; i++) {
+ virDomainShmemDefPtr shmem;
+ ctxt->node = nodes[i];
+ shmem = virDomainShmemDefParseXML(nodes[i], ctxt, flags);
+ if (!shmem)
+ goto error;
+
+ def->shmems[def->nshmems++] = shmem;
+ }
+ ctxt->node = node;
+ VIR_FREE(nodes);
/* analysis of the user namespace mapping */
if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
@@ -16828,6 +17020,56 @@ static int virDomainPanicDefFormat(virBufferPtr buf,
return 0;
}
+static int virDomainIvshmemDefFormat(virBufferPtr buf,
+ virDomainIvshmemDefPtr def)
+{
+ if (def->server.enabled)
+ virBufferAsprintf(buf, "<server path='%s'/>\n",
+ def->server.path);
+ if (def->size)
+ virBufferAsprintf(buf, "<size
unit='M'>%llu</size>\n",
+ def->size / (1024 * 1024));
+
+ if (def->server.enabled && def->msi.enabled) {
+ virBufferAddLit(buf, "<msi");
+ if (def->msi.vectors)
+ virBufferAsprintf(buf, " vectors='%u'",
def->msi.vectors);
+ if (def->msi.ioeventfd)
+ virBufferAsprintf(buf, " ioeventfd='%s'",
+ virTristateSwitchTypeToString(def->msi.ioeventfd));
+ virBufferAddLit(buf, "/>\n");
+ }
+
+ return 0;
+}
+
+static int virDomainShmemDefFormat(virBufferPtr buf,
+ virDomainShmemDefPtr def,
+ unsigned int flags)
+{
+ virBufferAsprintf(buf, "<shmem name='%s'
model='%s'>\n",
+ def->name, virDomainShmemModelTypeToString(def->model));
+
+ virBufferAdjustIndent(buf, 2);
+ switch (def->model) {
+ case VIR_DOMAIN_SHMEM_MODEL_IVSHMEM:
+ virDomainIvshmemDefFormat(buf, &def->data.ivshmem);
+ break;
+ default:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unexpected shem model %d"), def->model);
+ }
+
+ if (virDomainDeviceInfoIsSet(&def->info, flags) &&
+ virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
+ return -1;
+
+ virBufferAdjustIndent(buf, -2);
+ virBufferAddLit(buf, "</shmem>\n");
+
+ return 0;
+}
+
static int
virDomainRNGDefFormat(virBufferPtr buf,
virDomainRNGDefPtr def,
@@ -18377,6 +18619,10 @@ virDomainDefFormatInternal(virDomainDefPtr def,
virDomainPanicDefFormat(buf, def->panic) < 0)
goto error;
+ for (n = 0; n < def->nshmems; n++)
+ if (virDomainShmemDefFormat(buf, def->shmems[n], flags) < 0)
+ goto error;
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</devices>\n");
@@ -19742,6 +19988,7 @@ virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
case VIR_DOMAIN_DEVICE_SMARTCARD:
case VIR_DOMAIN_DEVICE_MEMBALLOON:
case VIR_DOMAIN_DEVICE_NVRAM:
+ case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Copying definition of '%d' type "
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f2df4eb..0c6aa21 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -136,6 +136,12 @@ typedef virDomainPanicDef *virDomainPanicDefPtr;
typedef struct _virDomainChrSourceDef virDomainChrSourceDef;
typedef virDomainChrSourceDef *virDomainChrSourceDefPtr;
+typedef struct _virDomainIvshmemDef virDomainIvshmemDef;
+typedef virDomainIvshmemDef *virDomainIvshmemDefPtr;
+
+typedef struct _virDomainShmemDef virDomainShmemDef;
+typedef virDomainShmemDef *virDomainShmemDefPtr;
+
/* Flags for the 'type' field in virDomainDeviceDef */
typedef enum {
VIR_DOMAIN_DEVICE_NONE = 0,
@@ -157,6 +163,7 @@ typedef enum {
VIR_DOMAIN_DEVICE_MEMBALLOON,
VIR_DOMAIN_DEVICE_NVRAM,
VIR_DOMAIN_DEVICE_RNG,
+ VIR_DOMAIN_DEVICE_SHMEM,
VIR_DOMAIN_DEVICE_LAST
} virDomainDeviceType;
@@ -184,6 +191,7 @@ struct _virDomainDeviceDef {
virDomainMemballoonDefPtr memballoon;
virDomainNVRAMDefPtr nvram;
virDomainRNGDefPtr rng;
+ virDomainShmemDefPtr shmem;
} data;
};
@@ -1370,6 +1378,12 @@ typedef enum {
VIR_DOMAIN_HUB_TYPE_LAST
} virDomainHubType;
+typedef enum {
+ VIR_DOMAIN_SHMEM_MODEL_IVSHMEM,
+
+ VIR_DOMAIN_SHMEM_MODEL_LAST
+} virDomainShmemModel;
+
typedef struct _virDomainGraphicsListenDef virDomainGraphicsListenDef;
typedef virDomainGraphicsListenDef *virDomainGraphicsListenDefPtr;
struct _virDomainGraphicsListenDef {
@@ -1486,6 +1500,28 @@ struct _virDomainNVRAMDef {
virDomainDeviceInfo info;
};
+struct _virDomainIvshmemDef {
+ unsigned long long size;
+ struct {
+ bool enabled;
+ char *path;
+ } server;
+ struct {
+ bool enabled;
+ unsigned vectors;
+ virTristateSwitch ioeventfd;
+ } msi;
+};
+
+struct _virDomainShmemDef {
+ int model; /* enum virDomainShmemModel */
+ char *name;
+ union {
+ virDomainIvshmemDef ivshmem;
+ } data;
+ virDomainDeviceInfo info;
+};
+
typedef enum {
VIR_DOMAIN_SMBIOS_NONE = 0,
VIR_DOMAIN_SMBIOS_EMULATE,
@@ -2007,6 +2043,9 @@ struct _virDomainDef {
size_t nrngs;
virDomainRNGDefPtr *rngs;
+ size_t nshmems;
+ virDomainShmemDefPtr *shmems;
+
/* Only 1 */
virDomainWatchdogDefPtr watchdog;
virDomainMemballoonDefPtr memballoon;
@@ -2204,6 +2243,7 @@ void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
void virDomainHubDefFree(virDomainHubDefPtr def);
void virDomainRedirdevDefFree(virDomainRedirdevDefPtr def);
void virDomainRedirFilterDefFree(virDomainRedirFilterDefPtr def);
+void virDomainShmemDefFree(virDomainShmemDefPtr def);
void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
virDomainDeviceDefPtr virDomainDeviceDefCopy(virDomainDeviceDefPtr src,
const virDomainDef *def,
@@ -2628,6 +2668,7 @@ VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy)
VIR_ENUM_DECL(virDomainHyperv)
VIR_ENUM_DECL(virDomainRNGModel)
VIR_ENUM_DECL(virDomainRNGBackend)
+VIR_ENUM_DECL(virDomainShmemModel)
VIR_ENUM_DECL(virDomainTPMModel)
VIR_ENUM_DECL(virDomainTPMBackend)
/* from libvirt.h */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e09ddd5..f86926e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -373,6 +373,8 @@ virDomainSaveStatus;
virDomainSaveXML;
virDomainSeclabelTypeFromString;
virDomainSeclabelTypeToString;
+virDomainShmemModelTypeFromString;
+virDomainShmemModelTypeToString;
virDomainShutdownReasonTypeFromString;
virDomainShutdownReasonTypeToString;
virDomainShutoffReasonTypeFromString;
--
1.9.3