This new cfg field was addded in 4.0 by 68a94cf528e6 "xm: Add maxvcpus support" and, more crucially these day, it is what xl supports. This removes the MAX_VIRT_CPUS limitation for such versions of Xen (since maxvcpus is simply a count, not a bit mask) which is particularly crucial on ARM where MAX_VIRT_CPUS == 1 (since all guests are expected to support vcpu placement, and therefore only the boot vcpu's info lives in the shared info page). Add a new test case to both XM and XL config tests covering this case. Note that although xm gained support for maxvcpus in Xen 4.0 the xend_config_format was never bumped beyond 4 and the internal handling remained in terms of vcpu_avail. Therefore the support for xend >= XEND_CONFIG_VERSION_4_0_0 is somewhat theoretical. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- src/xenconfig/xen_common.c | 72 ++++++++++++++++++++------- src/xenconfig/xen_xm.c | 7 +++ tests/xlconfigdata/test-paravirt-maxvcpus.cfg | 13 +++++ tests/xlconfigdata/test-paravirt-maxvcpus.xml | 28 +++++++++++ tests/xlconfigtest.c | 1 + tests/xmconfigdata/test-paravirt-maxvcpus.cfg | 13 +++++ tests/xmconfigdata/test-paravirt-maxvcpus.xml | 30 +++++++++++ tests/xmconfigtest.c | 1 + 8 files changed, 146 insertions(+), 19 deletions(-) create mode 100644 tests/xlconfigdata/test-paravirt-maxvcpus.cfg create mode 100644 tests/xlconfigdata/test-paravirt-maxvcpus.xml create mode 100644 tests/xmconfigdata/test-paravirt-maxvcpus.cfg create mode 100644 tests/xmconfigdata/test-paravirt-maxvcpus.xml diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c index 0890c73..6f2afcc 100644 --- a/src/xenconfig/xen_common.c +++ b/src/xenconfig/xen_common.c @@ -492,24 +492,49 @@ xenParsePCI(virConfPtr conf, virDomainDefPtr def) static int -xenParseCPUFeatures(virConfPtr conf, virDomainDefPtr def) +xenParseCPUFeatures(virConfPtr conf, virDomainDefPtr def, + int xendConfigVersion) { unsigned long count = 0; const char *str = NULL; int val = 0; - if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0 || - MAX_VIRT_CPUS < count) - return -1; + /* + * xend prior to 4.0 understands vcpus as maxvcpus and vcpu_avail + * as a bit map of which cpus are online (default is all). + * + * xend from 4.0 onwards understands maxvcpus as maxvcpus and + * vcpus as the number which are online (from 0..N-1). The + * upstream commit (68a94cf528e6 "xm: Add maxvcpus support") + * claims that if maxvcpus is omitted then the old behaviour + * (i.e. obeying vcpu_avail) is retained, but AFAICT it was not, + * in this case vcpu==maxcpus==online cpus. This is good for us + * because handling anything else would be fiddly. + * + * xl understands vcpus + maxvcpus, but not vcpu_avail + * (ever). + */ + if (xendConfigVersion < XEND_CONFIG_VERSION_4_0_0) { + if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0 || + MAX_VIRT_CPUS < count) + return -1; + def->maxvcpus = count; - def->maxvcpus = count; - if (xenConfigGetULong(conf, "vcpu_avail", &count, -1) < 0) - return -1; + if (xenConfigGetULong(conf, "vcpu_avail", &count, -1) < 0) + return -1; + def->vcpus = MIN(count_one_bits_l(count), def->maxvcpus); + } else { + if (xenConfigGetULong(conf, "vcpus", &count, 1) < 0) + return -1; + def->vcpus = count; + + if (xenConfigGetULong(conf, "maxvcpus", &count, def->vcpus) < 0) + return -1; + def->maxvcpus = count; + } - def->vcpus = MIN(count_one_bits_l(count), def->maxvcpus); if (xenConfigGetString(conf, "cpus", &str, NULL) < 0) return -1; - if (str && (virBitmapParse(str, 0, &def->cpumask, 4096) < 0)) return -1; @@ -1032,7 +1057,7 @@ xenParseConfigCommon(virConfPtr conf, if (xenParseEventsActions(conf, def) < 0) return -1; - if (xenParseCPUFeatures(conf, def) < 0) + if (xenParseCPUFeatures(conf, def, xendConfigVersion) < 0) return -1; if (xenParseTimeOffset(conf, def, xendConfigVersion) < 0) @@ -1519,19 +1544,28 @@ xenFormatCharDev(virConfPtr conf, virDomainDefPtr def) static int -xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def) +xenFormatCPUAllocation(virConfPtr conf, virDomainDefPtr def, + int xendConfigVersion) { int ret = -1; char *cpus = NULL; - if (xenConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) - goto cleanup; + if (xendConfigVersion >= XEND_CONFIG_VERSION_4_0_0) { + if (def->vcpus < def->maxvcpus && + xenConfigSetInt(conf, "maxvcpus", def->maxvcpus) < 0) + goto cleanup; + if (xenConfigSetInt(conf, "vcpus", def->vcpus) < 0) + goto cleanup; + } else { + if (xenConfigSetInt(conf, "vcpus", def->maxvcpus) < 0) + goto cleanup; - /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is - either 32, or 64 on a platform where long is big enough. */ - if (def->vcpus < def->maxvcpus && - xenConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0) - goto cleanup; + /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is + either 32, or 64 on a platform where long is big enough. */ + if (def->vcpus < def->maxvcpus && + xenConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0) + goto cleanup; + } if ((def->cpumask != NULL) && ((cpus = virBitmapFormat(def->cpumask)) == NULL)) { @@ -1826,7 +1860,7 @@ xenFormatConfigCommon(virConfPtr conf, if (xenFormatMem(conf, def) < 0) return -1; - if (xenFormatCPUAllocation(conf, def) < 0) + if (xenFormatCPUAllocation(conf, def, xendConfigVersion) < 0) return -1; if (xenFormatCPUFeatures(conf, def, xendConfigVersion) < 0) diff --git a/src/xenconfig/xen_xm.c b/src/xenconfig/xen_xm.c index a4d1203..a2981f7 100644 --- a/src/xenconfig/xen_xm.c +++ b/src/xenconfig/xen_xm.c @@ -482,6 +482,13 @@ xenParseXM(virConfPtr conf, if (xenParseConfigCommon(conf, def, caps, xendConfigVersion) < 0) goto cleanup; + /* + * xend vcpu_avail field is an integer bitmap, so cannot handle more than + * MAX_VIRT_CPUS. + */ + if (MAX_VIRT_CPUS < def->maxvcpus || MAX_VIRT_CPUS < def->vcpus) + goto cleanup; + if (xenParseXMOS(conf, def) < 0) goto cleanup; diff --git a/tests/xlconfigdata/test-paravirt-maxvcpus.cfg b/tests/xlconfigdata/test-paravirt-maxvcpus.cfg new file mode 100644 index 0000000..d506b75 --- /dev/null +++ b/tests/xlconfigdata/test-paravirt-maxvcpus.cfg @@ -0,0 +1,13 @@ +name = "XenGuest1" +uuid = "45b60f51-88a9-47a8-a3b3-5e66d71b2283" +maxmem = 512 +memory = 512 +maxvcpus = 8 +vcpus = 4 +localtime = 0 +on_poweroff = "preserve" +on_reboot = "restart" +on_crash = "preserve" +vif = [ "mac=5a:36:0e:be:00:09" ] +bootloader = "/usr/bin/pygrub" +disk = [ "/var/lib/xen/images/debian/disk.qcow2,qcow2,xvda,w,backendtype=qdisk" ] diff --git a/tests/xlconfigdata/test-paravirt-maxvcpus.xml b/tests/xlconfigdata/test-paravirt-maxvcpus.xml new file mode 100644 index 0000000..2e1f8f8 --- /dev/null +++ b/tests/xlconfigdata/test-paravirt-maxvcpus.xml @@ -0,0 +1,28 @@ +<domain type='xen'> + <name>XenGuest1</name> + <uuid>45b60f51-88a9-47a8-a3b3-5e66d71b2283</uuid> + <memory unit='KiB'>524288</memory> + <currentMemory unit='KiB'>524288</currentMemory> + <vcpu placement='static' current='4'>8</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type arch='x86_64' machine='xenpv'>linux</type> + </os> + <clock offset='utc' adjustment='reset'/> + <on_poweroff>preserve</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>preserve</on_crash> + <devices> + <disk type='file' device='disk'> + <driver name='qemu' type='qcow2'/> + <source file='/var/lib/xen/images/debian/disk.qcow2'/> + <target dev='xvda' bus='xen'/> + </disk> + <interface type='ethernet'> + <mac address='5a:36:0e:be:00:09'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xlconfigtest.c b/tests/xlconfigtest.c index 08c43fb..b6f9b84 100644 --- a/tests/xlconfigtest.c +++ b/tests/xlconfigtest.c @@ -193,6 +193,7 @@ mymain(void) ret = -1; \ } while (0) + DO_TEST("paravirt-maxvcpus", 5); DO_TEST("new-disk", 5); DO_TEST("spice", 5); DO_TEST("spice-features", 5); diff --git a/tests/xmconfigdata/test-paravirt-maxvcpus.cfg b/tests/xmconfigdata/test-paravirt-maxvcpus.cfg new file mode 100644 index 0000000..8d1ac4d --- /dev/null +++ b/tests/xmconfigdata/test-paravirt-maxvcpus.cfg @@ -0,0 +1,13 @@ +name = "XenGuest1" +uuid = "c7a5fdb0-cdaf-9455-926a-d65c16db1809" +maxmem = 579 +memory = 394 +maxvcpus = 4 +vcpus = 2 +localtime = 0 +on_poweroff = "destroy" +on_reboot = "restart" +on_crash = "restart" +vif = [ "mac=00:16:3e:66:94:9c,bridge=br0,script=vif-bridge" ] +bootloader = "/usr/bin/pygrub" +disk = [ "phy:/dev/HostVG/XenGuest1,xvda,w" ] diff --git a/tests/xmconfigdata/test-paravirt-maxvcpus.xml b/tests/xmconfigdata/test-paravirt-maxvcpus.xml new file mode 100644 index 0000000..52463d8 --- /dev/null +++ b/tests/xmconfigdata/test-paravirt-maxvcpus.xml @@ -0,0 +1,30 @@ +<domain type='xen'> + <name>XenGuest1</name> + <uuid>c7a5fdb0-cdaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>592896</memory> + <currentMemory unit='KiB'>403456</currentMemory> + <vcpu placement='static' current='2'>4</vcpu> + <bootloader>/usr/bin/pygrub</bootloader> + <os> + <type arch='i686' machine='xenpv'>linux</type> + </os> + <clock offset='utc' adjustment='reset'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>restart</on_crash> + <devices> + <disk type='block' device='disk'> + <driver name='phy'/> + <source dev='/dev/HostVG/XenGuest1'/> + <target dev='xvda' bus='xen'/> + </disk> + <interface type='bridge'> + <mac address='00:16:3e:66:94:9c'/> + <source bridge='br0'/> + <script path='vif-bridge'/> + </interface> + <console type='pty'> + <target type='xen' port='0'/> + </console> + </devices> +</domain> diff --git a/tests/xmconfigtest.c b/tests/xmconfigtest.c index 79b09ca..ff1f52b 100644 --- a/tests/xmconfigtest.c +++ b/tests/xmconfigtest.c @@ -220,6 +220,7 @@ mymain(void) DO_TEST("paravirt-net-e1000", 3); DO_TEST("paravirt-net-vifname", 3); DO_TEST("paravirt-vcpu", 2); + DO_TEST("paravirt-maxvcpus", 5); DO_TEST("fullvirt-old-cdrom", 1); DO_TEST("fullvirt-new-cdrom", 2); DO_TEST("fullvirt-utc", 2); -- 2.1.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list