[PATCH 0/6] conf: add vlen tag for RISC-V CPUs
RISC-V CPUs may 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'> According to the RISC-V ISA specification vlen must be a power of 2 in the range 8 to 65536. A configuration test is provided. Heinrich Schuchardt (6): conf: add vlen tag for RISC-V CPUs schemas: add cpuVlen definition for RISC-V vector length qemu: validate that CPU vlen is only used with RISC-V qemu: emit vlen= CPU property on the command line tests: provide vlen configuration test docs: add vlen to formatdomain documentation docs/formatdomain.rst | 13 ++++++++ src/conf/cpu_conf.c | 25 +++++++++++++++ src/conf/cpu_conf.h | 1 + src/conf/schemas/cputypes.rng | 11 +++++++ src/qemu/qemu_command.c | 3 ++ src/qemu/qemu_validate.c | 9 ++++++ .../riscv64-virt-vlen.riscv64-latest.args | 31 +++++++++++++++++++ .../riscv64-virt-vlen.riscv64-latest.xml | 26 ++++++++++++++++ tests/qemuxmlconfdata/riscv64-virt-vlen.xml | 26 ++++++++++++++++ tests/qemuxmlconftest.c | 2 ++ 10 files changed, 147 insertions(+) create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.args create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.xml create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.xml -- 2.53.0
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
Add a new 'cpuVlen' RNG define for the <vlen value='N'/> CPU sub-element and reference it as optional inside the 'guestcpu' grammar. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- src/conf/schemas/cputypes.rng | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/conf/schemas/cputypes.rng b/src/conf/schemas/cputypes.rng index 8edf1d14e3..5af76ee410 100644 --- a/src/conf/schemas/cputypes.rng +++ b/src/conf/schemas/cputypes.rng @@ -331,6 +331,14 @@ </element> </define> + <define name="cpuVlen"> + <element name="vlen"> + <attribute name="value"> + <ref name="positiveInteger"/> + </attribute> + </element> + </define> + <define name="hostcpu"> <element name="cpu"> <interleave> @@ -471,6 +479,9 @@ <optional> <ref name="cpuMaxPhysAddr"/> </optional> + <optional> + <ref name="cpuVlen"/> + </optional> </interleave> </element> </define> -- 2.53.0
The RISC-V vector register length is only relevant for RISC-V guest CPUs. Reject <vlen> if configured for any other architecture. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- src/qemu/qemu_validate.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c index 439d4b1916..86ace2a8f6 100644 --- a/src/qemu/qemu_validate.c +++ b/src/qemu/qemu_validate.c @@ -451,6 +451,15 @@ qemuValidateDomainDefCpu(virQEMUDriver *driver, } } + if (cpu->vlen) { + if (!ARCH_IS_RISCV(def->os.arch)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("CPU vector length specification is not supported for '%1$s' architecture"), + virArchToString(def->os.arch)); + return -1; + } + } + if (cpu->model || cpu->mode != VIR_CPU_MODE_CUSTOM) { switch ((virCPUMode) cpu->mode) { case VIR_CPU_MODE_HOST_PASSTHROUGH: -- 2.53.0
When the RISC-V vector length is configured via <vlen value='N'/>, append ',vlen=N' to the -cpu argument, e.g. '-cpu rv64,vlen=256'. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- src/qemu/qemu_command.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e726dc661c..56e217874e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6508,6 +6508,9 @@ qemuBuildCpuModelArgStr(virQEMUDriver *driver, if (cpu->vendor_id) virBufferAsprintf(buf, ",vendor=%s", cpu->vendor_id); + if (cpu->vlen) + virBufferAsprintf(buf, ",vlen=%u", cpu->vlen); + if (ARCH_IS_X86(def->os.arch) && virQEMUCapsGetCPUFeatures(qemuCaps, def->virtType, false, &knownFeatures) < 0) return -1; -- 2.53.0
Provide test data for checking that vlen can be set on RISC-V. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- .../riscv64-virt-vlen.riscv64-latest.args | 31 +++++++++++++++++++ .../riscv64-virt-vlen.riscv64-latest.xml | 26 ++++++++++++++++ tests/qemuxmlconfdata/riscv64-virt-vlen.xml | 26 ++++++++++++++++ tests/qemuxmlconftest.c | 2 ++ 4 files changed, 85 insertions(+) create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.args create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.xml create mode 100644 tests/qemuxmlconfdata/riscv64-virt-vlen.xml diff --git a/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.args b/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.args new file mode 100644 index 0000000000..1f827b306c --- /dev/null +++ b/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.args @@ -0,0 +1,31 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/var/lib/libvirt/qemu/domain--1-guest \ +USER=test \ +LOGNAME=test \ +XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ +XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ +XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ +/usr/bin/qemu-system-riscv64 \ +-name guest=guest,debug-threads=on \ +-S \ +-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +-machine virt,usb=off,dump-guest-core=off,memory-backend=riscv_virt_board.ram,acpi=off \ +-accel tcg \ +-cpu rv64,vlen=256,v=on \ +-m size=4194304k \ +-object '{"qom-type":"memory-backend-ram","id":"riscv_virt_board.ram","size":4294967296}' \ +-overcommit mem-lock=off \ +-smp 4,sockets=4,cores=1,threads=1 \ +-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ +-display none \ +-no-user-config \ +-nodefaults \ +-chardev socket,id=charmonitor,fd=@mon-fd@,server=on,wait=off \ +-mon chardev=charmonitor,id=monitor,mode=control \ +-rtc base=utc \ +-no-shutdown \ +-boot strict=on \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.xml b/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.xml new file mode 100644 index 0000000000..67545ba8d4 --- /dev/null +++ b/tests/qemuxmlconfdata/riscv64-virt-vlen.riscv64-latest.xml @@ -0,0 +1,26 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='riscv64' machine='virt'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>rv64</model> + <vlen value='256'/> + <feature policy='require' name='v'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-riscv64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/riscv64-virt-vlen.xml b/tests/qemuxmlconfdata/riscv64-virt-vlen.xml new file mode 100644 index 0000000000..67545ba8d4 --- /dev/null +++ b/tests/qemuxmlconfdata/riscv64-virt-vlen.xml @@ -0,0 +1,26 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>4194304</memory> + <currentMemory unit='KiB'>4194304</currentMemory> + <vcpu placement='static'>4</vcpu> + <os> + <type arch='riscv64' machine='virt'>hvm</type> + <boot dev='hd'/> + </os> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>rv64</model> + <vlen value='256'/> + <feature policy='require' name='v'/> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-riscv64</emulator> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index a1389775b9..929c844e90 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -3166,6 +3166,8 @@ mymain(void) DO_TEST_CAPS_ARCH_LATEST("riscv64-virt-features-aia", "riscv64"); + DO_TEST_CAPS_ARCH_LATEST("riscv64-virt-vlen", "riscv64"); + DO_TEST_CAPS_LATEST("virtio-9p-multidevs"); DO_TEST_CAPS_LATEST("virtio-9p-createmode"); -- 2.53.0
Describe the usage of the vlen attribute for RISC-V CPUs. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- docs/formatdomain.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index a861f9f177..3856bc8921 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1810,7 +1810,20 @@ In case no restrictions need to be put on CPU model and its features, a simpler address bits for ``passthrough`` mode, i.e. in case the host CPU reports more bits than that, ``limit`` is used. :since:`Since 9.3.0` +``vlen`` + :since:`Since 12.6.0` the ``vlen`` element describes the length, in bits, + of the vector registers exposed to the guest CPU. This is currently only + supported for RISC-V guests with the ``V`` vector extension enabled, and + corresponds to the QEMU ``vlen`` CPU property, e.g. + ``-cpu rva23s64,vlen=256``. The element is omitted if the vector register + length is not configured, in which case the hypervisor default is used. + + ``value`` + This mandatory attribute specifies the vector register length in bits. + The value must be a power of two in the range [8, 65536]. + Guest NUMA topology can be specified using the ``numa`` element. + :since:`Since 0.9.8` :: -- 2.53.0
participants (1)
-
Heinrich Schuchardt