From d0e4be9d0297494ba0e23843593f734234ddb08f Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Wed, 13 Jul 2016 14:09:20 +0200 Subject: [PATCH] Introduce SMM feature Since its release of 2.4.0 qemu is able to enable System Management Module in the firmware, or disable it. We should expose this capability in the XML. Unfortunately, there's no good way to determine whether the binary we are talking to supports it. I mean, if qemu's run with real machine type, the smm attribute can be seen in 'qom-list /machine' output. But it's not there when qemu's run with -M none. Therefore we're stuck with version based check. Signed-off-by: Michal Privoznik --- docs/formatdomain.html.in | 6 ++++ docs/schemas/domaincommon.rng | 9 ++++++ src/conf/domain_conf.c | 5 +++- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 16 +++++++++++ src/qemu/qemu_capabilities.h | 4 +++ src/qemu/qemu_command.c | 12 ++++++++ .../caps_2.4.0.x86_64.xml | 1 + .../caps_2.5.0.x86_64.xml | 1 + .../caps_2.6.0-gicv2.aarch64.xml | 1 + .../caps_2.6.0-gicv3.aarch64.xml | 1 + .../caps_2.6.0.ppc64le.xml | 1 + .../caps_2.6.0.x86_64.xml | 1 + .../qemuxml2argv-machine-smm-opt.args | 25 +++++++++++++++++ .../qemuxml2argv-machine-smm-opt.xml | 28 +++++++++++++++++++ tests/qemuxml2argvtest.c | 7 +++++ 16 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fa88839ec5..dabe604ec2 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1680,6 +1680,12 @@ values are 2, 3 and host. Since 1.2.16 +
smm
+
Enable System Management Mode. Possible values are + on and off. The default is left + for hypervisor to decide. + Since 2.1.0 +

Time keeping

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index cb9f1349f3..5233766239 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4325,6 +4325,15 @@ + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e58046be89..3d3e74ca2b 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -137,7 +137,8 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST, "capabilities", "pmu", "vmport", - "gic") + "gic", + "smm") VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, VIR_DOMAIN_CAPABILITIES_POLICY_LAST, "default", @@ -16348,6 +16349,7 @@ virDomainDefParseXML(xmlDocPtr xml, case VIR_DOMAIN_FEATURE_PMU: case VIR_DOMAIN_FEATURE_PVSPINLOCK: case VIR_DOMAIN_FEATURE_VMPORT: + case VIR_DOMAIN_FEATURE_SMM: node = ctxt->node; ctxt->node = nodes[i]; if ((tmp = virXPathString("string(./@state)", ctxt))) { @@ -23331,6 +23333,7 @@ virDomainDefFormatInternal(virDomainDefPtr def, case VIR_DOMAIN_FEATURE_PMU: case VIR_DOMAIN_FEATURE_PVSPINLOCK: case VIR_DOMAIN_FEATURE_VMPORT: + case VIR_DOMAIN_FEATURE_SMM: switch ((virTristateSwitch) def->features[i]) { case VIR_TRISTATE_SWITCH_LAST: case VIR_TRISTATE_SWITCH_ABSENT: diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index b2e905dd94..cea7d1d7d6 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1602,6 +1602,7 @@ typedef enum { VIR_DOMAIN_FEATURE_PMU, VIR_DOMAIN_FEATURE_VMPORT, VIR_DOMAIN_FEATURE_GIC, + VIR_DOMAIN_FEATURE_SMM, VIR_DOMAIN_FEATURE_LAST } virDomainFeature; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 002fbe3a72..3eb26c5030 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -339,6 +339,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "tls-creds-x509", /* 230 */ "display", "intel-iommu", + "smm", ); @@ -3502,6 +3503,10 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 2004000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_VHOSTUSER_MULTIQUEUE); + /* smm option is supported from v2.4.0 */ + if (qemuCaps->version >= 2004000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACHINE_SMM_OPT); + /* Since 2.4.50 ARM virt machine supports gic-version option */ if (qemuCaps->version >= 2004050) virQEMUCapsSet(qemuCaps, QEMU_CAPS_MACH_VIRT_GIC_VERSION); @@ -4020,6 +4025,17 @@ virQEMUCapsSupportsVmport(virQEMUCapsPtr qemuCaps, } +bool +virQEMUCapsSupportsSMM(virQEMUCapsPtr qemuCaps, + const virDomainDef *def) +{ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_SMM_OPT)) + return false; + + return qemuDomainMachineIsQ35(def); +} + + bool virQEMUCapsIsMachineSupported(virQEMUCapsPtr qemuCaps, const char *canonical_machine) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 72e763abec..3a1aa52d3c 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -372,6 +372,7 @@ typedef enum { QEMU_CAPS_OBJECT_TLS_CREDS_X509, /* -object tls-creds-x509 */ QEMU_CAPS_DISPLAY, /* -display */ QEMU_CAPS_DEVICE_INTEL_IOMMU, /* -device intel-iommu */ + QEMU_CAPS_MACHINE_SMM_OPT, /* -machine xxx,smm=on/off/auto */ QEMU_CAPS_LAST /* this must always be the last item */ } virQEMUCapsFlags; @@ -408,6 +409,9 @@ bool virQEMUCapsHasPCIMultiBus(virQEMUCapsPtr qemuCaps, bool virQEMUCapsSupportsVmport(virQEMUCapsPtr qemuCaps, const virDomainDef *def); +bool virQEMUCapsSupportsSMM(virQEMUCapsPtr qemuCaps, + const virDomainDef *def); + char *virQEMUCapsFlagsString(virQEMUCapsPtr qemuCaps); const char *virQEMUCapsGetBinary(virQEMUCapsPtr qemuCaps); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 6f909172b9..159d78a1bc 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6970,6 +6970,7 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, } } else { virTristateSwitch vmport = def->features[VIR_DOMAIN_FEATURE_VMPORT]; + virTristateSwitch smm = def->features[VIR_DOMAIN_FEATURE_SMM]; virCommandAddArg(cmd, "-machine"); virBufferAdd(&buf, def->os.machine, -1); @@ -6999,6 +7000,17 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, virTristateSwitchTypeToString(vmport)); } + if (smm) { + if (!virQEMUCapsSupportsSMM(qemuCaps, def)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("smm is not available with this QEMU binary")); + goto cleanup; + } + + virBufferAsprintf(&buf, ",smm=%s", + virTristateSwitchTypeToString(smm)); + } + if (def->mem.dump_core) { if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DUMP_GUEST_CORE)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", diff --git a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml index 80085d5623..339ee1fe14 100644 --- a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml @@ -183,6 +183,7 @@ + 2004000 0 diff --git a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml index fad3291b89..c1a68d085a 100644 --- a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml @@ -188,6 +188,7 @@ + 2005000 0 diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml index 4ed88bc97b..85d7d3fbf9 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml @@ -157,6 +157,7 @@ + 2005094 0 diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml index 024596d304..deb12577e3 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml @@ -157,6 +157,7 @@ + 2005094 0 diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml index e66433c2c5..2b7ea0e8cc 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml @@ -151,6 +151,7 @@ + 2005094 0 diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml index 653ec7511a..495c1140b1 100644 --- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml @@ -194,6 +194,7 @@ + 2006000 0 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.args b/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.args new file mode 100644 index 0000000000..e49d7e921f --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.args @@ -0,0 +1,25 @@ +LC_ALL=C \ +PATH=/bin \ +HOME=/home/test \ +USER=test \ +LOGNAME=test \ +QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name QEMUGuest1 \ +-S \ +-machine q35,accel=tcg,smm=on \ +-m 214 \ +-smp 1,sockets=1,cores=1,threads=1 \ +-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \ +-nographic \ +-nodefaults \ +-monitor unix:/tmp/lib/domain--1-QEMUGuest1/monitor.sock,server,nowait \ +-no-acpi \ +-boot c \ +-device i82801b11-bridge,id=pci.1,bus=pcie.0,addr=0x1e \ +-device pci-bridge,chassis_nr=2,id=pci.2,bus=pci.1,addr=0x0 \ +-device virtio-scsi-pci,id=scsi0,bus=pci.2,addr=0x1 \ +-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-scsi0-0-0-0 \ +-device scsi-disk,bus=scsi0.0,channel=0,scsi-id=0,lun=0,\ +drive=drive-scsi0-0-0-0,id=scsi0-0-0-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.2,addr=0x2 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.xml b/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.xml new file mode 100644 index 0000000000..b964b5ead6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-machine-smm-opt.xml @@ -0,0 +1,28 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 751d692533..bdf15d4042 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -618,6 +618,13 @@ mymain(void) QEMU_CAPS_DUMP_GUEST_CORE); DO_TEST_FAILURE("machine-core-on", NONE); DO_TEST_FAILURE("machine-core-on", QEMU_CAPS_MACHINE_OPT); + DO_TEST("machine-smm-opt", + QEMU_CAPS_DEVICE_DMI_TO_PCI_BRIDGE, + QEMU_CAPS_DEVICE_PCI_BRIDGE, + QEMU_CAPS_ICH9_AHCI, + QEMU_CAPS_MACHINE_OPT, + QEMU_CAPS_MACHINE_SMM_OPT, + QEMU_CAPS_VIRTIO_SCSI); DO_TEST("machine-usb-opt", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_MACHINE_USB_OPT); DO_TEST("machine-vmport-opt", QEMU_CAPS_MACHINE_OPT,