RISC-V CPUs provide a scalable vector extension. The length of the vector registers is implementation specific. QEMU allows to set the vector length as a CPU property, e.g. '-cpu rva23s64,vlen=256'. To describe this feature a new CPU tag is introduced <vlen value='N'> where conforming to the RISC-V ISA specification vlen must be a power of 2 in the range 8 to 65536. The current QEMU release has tighter bounds depending on the chosen vector extensions: * max_vlen = 1024 * min_vlen = 32 (zve32x), 64 (zve64x), or 128 (V) This patch checks the configuration against the bounds of the ISA specification. This patch only covers the configuration management for vlen. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- src/conf/cpu_conf.c | 25 +++++++++++++++++++++++++ src/conf/cpu_conf.h | 1 + 2 files changed, 26 insertions(+) diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index f5a2004ee6..331f806968 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -250,6 +250,7 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) copy->sigFamily = cpu->sigFamily; copy->sigModel = cpu->sigModel; copy->sigStepping = cpu->sigStepping; + copy->vlen = cpu->vlen; if (cpu->cache) { copy->cache = g_new0(virCPUCacheDef, 1); @@ -356,6 +357,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, g_autofree xmlNodePtr *nodes = NULL; xmlNodePtr topology = NULL; xmlNodePtr maxphysaddrNode = NULL; + xmlNodePtr vlenNode = NULL; g_autofree xmlNodePtr *cacheNodes = NULL; ssize_t ncacheNodes = 0; VIR_XPATH_NODE_AUTORESTORE(ctxt) @@ -691,6 +693,20 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, } + if ((vlenNode = virXPathNode("./vlen[1]", ctxt))) { + if (virXMLPropUInt(vlenNode, "value", 10, + VIR_XML_PROP_REQUIRED | VIR_XML_PROP_NONZERO, + &def->vlen) < 0) + return -1; + + if (def->vlen < 8 || def->vlen > 65536 || + (def->vlen & (def->vlen - 1)) != 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("invalid CPU vlen value, must be a power of two in range [8, 65536]")); + return -1; + } + } + *cpu = g_steal_pointer(&def); return 0; } @@ -875,6 +891,9 @@ virCPUDefFormatBuf(virBuffer *buf, virBufferAddLit(buf, "/>\n"); } + if (def->vlen) + virBufferAsprintf(buf, "<vlen value='%u'/>\n", def->vlen); + for (i = 0; i < def->nfeatures; i++) { virCPUFeatureDef *feature = def->features + i; @@ -1175,6 +1194,12 @@ virCPUDefIsEqual(virCPUDef *src, return false; } + if (src->vlen != dst->vlen) { + MISMATCH(_("Target CPU vlen %1$u does not match source %2$u"), + dst->vlen, src->vlen); + return false; + } + if (src->nfeatures != dst->nfeatures) { MISMATCH(_("Target CPU feature count %1$zu does not match source %2$zu"), dst->nfeatures, src->nfeatures); diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index 0cac1a1489..406deb5e0b 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -154,6 +154,7 @@ struct _virCPUDef { unsigned int sigFamily; unsigned int sigModel; unsigned int sigStepping; + unsigned int vlen; /* RISC-V vector register length in bits; 0 for unspecified */ size_t nfeatures; size_t nfeatures_max; virCPUFeatureDef *features; -- 2.53.0