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 <mprivozn@redhat.com>
This commit is contained in:
Michal Privoznik 2016-07-13 14:09:20 +02:00
parent 90b42f0fad
commit d0e4be9d02
16 changed files with 118 additions and 1 deletions

View File

@ -1680,6 +1680,12 @@
values are <code>2</code>, <code>3</code> and <code>host</code>.
<span class="since">Since 1.2.16</span>
</dd>
<dt><code>smm</code></dt>
<dd>Enable System Management Mode. Possible values are
<code>on</code> and <code>off</code>. The default is left
for hypervisor to decide.
<span class="since">Since 2.1.0</span>
</dd>
</dl>
<h3><a name="elementsTime">Time keeping</a></h3>

View File

@ -4325,6 +4325,15 @@
</optional>
</element>
</optional>
<optional>
<element name="smm">
<optional>
<attribute name="state">
<ref name="virOnOff"/>
</attribute>
</optional>
</element>
</optional>
</interleave>
</element>
</optional>

View File

@ -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:

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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",

View File

@ -183,6 +183,7 @@
<flag name='drive-detect-zeroes'/>
<flag name='display'/>
<flag name='intel-iommu'/>
<flag name='smm'/>
<version>2004000</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -188,6 +188,7 @@
<flag name='tls-creds-x509'/>
<flag name='display'/>
<flag name='intel-iommu'/>
<flag name='smm'/>
<version>2005000</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -157,6 +157,7 @@
<flag name='drive-detect-zeroes'/>
<flag name='tls-creds-x509'/>
<flag name='display'/>
<flag name='smm'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -157,6 +157,7 @@
<flag name='drive-detect-zeroes'/>
<flag name='tls-creds-x509'/>
<flag name='display'/>
<flag name='smm'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -151,6 +151,7 @@
<flag name='drive-detect-zeroes'/>
<flag name='tls-creds-x509'/>
<flag name='display'/>
<flag name='smm'/>
<version>2005094</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -194,6 +194,7 @@
<flag name='tls-creds-x509'/>
<flag name='display'/>
<flag name='intel-iommu'/>
<flag name='smm'/>
<version>2006000</version>
<kvmVersion>0</kvmVersion>
<package></package>

View File

@ -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

View File

@ -0,0 +1,28 @@
<domain type='qemu'>
<name>QEMUGuest1</name>
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
<memory unit='KiB'>219100</memory>
<currentMemory unit='KiB'>219100</currentMemory>
<vcpu placement='static'>1</vcpu>
<os>
<type arch='x86_64' machine='q35'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<smm state='on'/>
</features>
<clock offset='utc'/>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<devices>
<emulator>/usr/bin/qemu</emulator>
<disk type='block' device='disk'>
<source dev='/dev/HostVG/QEMUGuest1'/>
<target dev='sda' bus='scsi'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<controller type='scsi' index='0'/>
<memballoon model='virtio'/>
</devices>
</domain>

View File

@ -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,