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

Reply via email to