Skip to content

Commit 434e30f

Browse files
author
Adam Spiers
committed
Add detection of SEV support from QEMU/AMD-SP/libvirt on AMD hosts
In order to support booting of SEV-enabled guests on AMD hosts which are SEV-capable, we first need to be able to automatically detect which hosts are capable of supporting SEV. This requires checking for support in two places: - The sev parameter of the kvm_amd kernel module (which indicates that the kernel provides support) - The host's libvirt domain capabilities, as indicated in the response from a virConnectGetDomainCapabilities() API call; if the <features> element includes <sev supported='yes'/> then this indicates that both QEMU and the AMD Secure Processor (AMD-SP) support SEV functionality, whereas <sev supported='no'/> indicates that QEMU doesn't support it, and the absence of any <sev> element indicates that libvirt doesn't even know about the feature: https://libvirt.org/git/?p=libvirt.git;a=commit;h=6688393c6b222b5d7cba238f21d55134611ede9c This commit addresses the second of these two checks. Subsequent commits will address the first, add logic which combines both checks, provide a new standard trait which indicates that both checks have passed, and of course ultimately make use of that new trait. blueprint: amd-sev-libvirt-support Change-Id: I4c35b6a27db05349213429422ffe62adb09bd921
1 parent 297f3ba commit 434e30f

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

nova/tests/unit/virt/libvirt/fakelibvirt.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,17 @@ def getDomainCapabilities(self, emulatorbin, arch, machine_type,
15051505
<gic supported='no'/>
15061506
</features>'''
15071507

1508+
_domain_capability_features_with_SEV = ''' <features>
1509+
<gic supported='no'/>
1510+
<sev supported='yes'>
1511+
<cbitpos>47</cbitpos>
1512+
<reducedPhysBits>1</reducedPhysBits>
1513+
</sev>
1514+
</features>'''
1515+
1516+
_domain_capability_features_with_SEV_unsupported = \
1517+
_domain_capability_features_with_SEV.replace('yes', 'no')
1518+
15081519
def getCapabilities(self):
15091520
"""Return spoofed capabilities."""
15101521
numa_topology = self.host_info.numa_topology

nova/tests/unit/virt/libvirt/test_host.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,28 @@ def test_get_domain_capabilities_no_features(self):
658658
features = caps.features
659659
self.assertEqual([], features)
660660

661+
def _test_get_domain_capabilities_sev(self, supported):
662+
caps = self._test_get_domain_capabilities()
663+
self.assertEqual(vconfig.LibvirtConfigDomainCaps, type(caps))
664+
features = caps.features
665+
self.assertEqual(1, len(features))
666+
sev = features[0]
667+
self.assertEqual(vconfig.LibvirtConfigDomainCapsFeatureSev, type(sev))
668+
self.assertEqual(supported, sev.supported)
669+
670+
@mock.patch.object(
671+
fakelibvirt.virConnect, '_domain_capability_features', new=
672+
fakelibvirt.virConnect._domain_capability_features_with_SEV_unsupported
673+
)
674+
def test_get_domain_capabilities_sev_unsupported(self):
675+
self._test_get_domain_capabilities_sev(False)
676+
677+
@mock.patch.object(
678+
fakelibvirt.virConnect, '_domain_capability_features',
679+
new=fakelibvirt.virConnect._domain_capability_features_with_SEV)
680+
def test_get_domain_capabilities_sev_supported(self):
681+
self._test_get_domain_capabilities_sev(True)
682+
661683
@mock.patch.object(fakelibvirt.virConnect, "getHostname")
662684
def test_get_hostname_caching(self, mock_hostname):
663685
mock_hostname.return_value = "foo"

nova/virt/libvirt/config.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ def parse_dom(self, xmldoc):
147147

148148
for c in xmldoc.getchildren():
149149
feature = None
150-
# TODO(aspiers): add supported features here
150+
if c.tag == "sev":
151+
feature = LibvirtConfigDomainCapsFeatureSev()
151152
if feature:
152153
feature.parse_dom(c)
153154
self.features.append(feature)
@@ -165,6 +166,20 @@ def format_dom(self):
165166
raise RuntimeError(_('BUG: tried to generate domainCapabilities XML'))
166167

167168

169+
class LibvirtConfigDomainCapsFeatureSev(LibvirtConfigObject):
170+
171+
def __init__(self, **kwargs):
172+
super(LibvirtConfigDomainCapsFeatureSev, self).__init__(
173+
root_name='sev', **kwargs)
174+
self.supported = False
175+
176+
def parse_dom(self, xmldoc):
177+
super(LibvirtConfigDomainCapsFeatureSev, self).parse_dom(xmldoc)
178+
179+
if xmldoc.get('supported') == 'yes':
180+
self.supported = True
181+
182+
168183
class LibvirtConfigCapsNUMATopology(LibvirtConfigObject):
169184

170185
def __init__(self, **kwargs):

0 commit comments

Comments
 (0)