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@xxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list