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 <[email protected]>
---
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