diff --git a/nova/tests/unit/virt/libvirt/test_driver.py b/nova/tests/unit/virt/libvirt/test_driver.py index fd4a3e181355..ad43d287e070 100644 --- a/nova/tests/unit/virt/libvirt/test_driver.py +++ b/nova/tests/unit/virt/libvirt/test_driver.py @@ -3787,6 +3787,53 @@ class LibvirtConnTestCase(test.NoDBTestCase, None, None, flavor, image_meta, ) + @mock.patch.object( + fakelibvirt.virConnect, '_domain_capability_features', new= + fakelibvirt.virConnect._domain_capability_features_with_SEV + ) + @mock.patch.object(host.Host, "_check_machine_type", new=mock.Mock()) + def test_get_guest_config_memory_encryption(self): + """Generate a guest with memory encryption. + + This configures an memory encryption. + """ + self.flags(virt_type="kvm", group='libvirt') + + drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True) + drvr._host._supports_amd_sev = True + drvr._host._supports_amd_sev_es = False + instance_ref = objects.Instance(**self.test_instance) + image_meta = objects.ImageMeta.from_dict({ + "hw_architecture": fields.Architecture.X86_64, + "disk_format": "raw", + "properties": { + "hw_machine_type": "q35", + "hw_firmware_type": "uefi", + "hw_mem_encryption": True, + } + }) + + disk_info = blockinfo.get_disk_info( + CONF.libvirt.virt_type, + instance_ref, + image_meta, + ) + + cfg = drvr._get_guest_config( + instance_ref, + _fake_network_info(self), + image_meta, + disk_info, + ) + + # NOTE(tkajinm): vmcoreinfo should be disabled in this case + self.assertEqual(2, len(cfg.features)) + for idx, device_type in enumerate([ + vconfig.LibvirtConfigGuestFeatureACPI, + vconfig.LibvirtConfigGuestFeatureAPIC, + ]): + self.assertIsInstance(cfg.features[idx], device_type) + def _test_get_mem_encryption_config( self, expected=None, host_sev_enabled=False, enc_extra_spec=None, enc_image_prop=None, hw_machine_type=None, hw_firmware_type=None): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 355624ffae70..2e22810c280e 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -6689,8 +6689,11 @@ class LibvirtDriver(driver.ComputeDriver): fields.Architecture.I686, fields.Architecture.X86_64, fields.Architecture.AARCH64, ): - guest.add_feature( - vconfig.LibvirtConfigGuestFeatureVMCoreInfo()) + # VMCoreInfo device requires DMA between guest OS and host + # OS, which is prohibited when guest memory is encrypted. + if not self._get_mem_encryption_config(flavor, image_meta): + guest.add_feature( + vconfig.LibvirtConfigGuestFeatureVMCoreInfo()) if hide_hypervisor_id: guest.add_feature( diff --git a/releasenotes/notes/bug-2117170-disable-vmcoreinfo-when-memory-encryption-is-enabled-142e64f6b9ef3135.yaml b/releasenotes/notes/bug-2117170-disable-vmcoreinfo-when-memory-encryption-is-enabled-142e64f6b9ef3135.yaml new file mode 100644 index 000000000000..259f0662d9c4 --- /dev/null +++ b/releasenotes/notes/bug-2117170-disable-vmcoreinfo-when-memory-encryption-is-enabled-142e64f6b9ef3135.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + [`bug 2117170 `_] Libvirt + driver no longer enables VMCoreInfo device when an instance has memory + encryption is enabled, to avoid kernel crash caused by fw_cfg device in + guest requiring DMA.