diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index aa90eab229..d9c2b7c57c 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -23,6 +23,7 @@ #include "qemu_capabilities.h" #include "viralloc.h" +#include "virarch.h" #include "vircrypto.h" #include "virlog.h" #include "virerror.h" @@ -662,6 +663,7 @@ struct _virQEMUCaps { virObject parent; bool kvmSupportsNesting; + bool kvmSupportsSecureGuest; char *binary; time_t ctime; @@ -1907,6 +1909,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) ret->invalidation = qemuCaps->invalidation; ret->kvmSupportsNesting = qemuCaps->kvmSupportsNesting; + ret->kvmSupportsSecureGuest = qemuCaps->kvmSupportsSecureGuest; ret->ctime = qemuCaps->ctime; @@ -4404,6 +4407,9 @@ virQEMUCapsLoadCache(virArch hostArch, if (virXPathBoolean("boolean(./kvmSupportsNesting)", ctxt) > 0) qemuCaps->kvmSupportsNesting = true; + if (virXPathBoolean("boolean(./kvmSupportsSecureGuest)", ctxt) > 0) + qemuCaps->kvmSupportsSecureGuest = true; + ret = 0; cleanup: VIR_FREE(str); @@ -4641,6 +4647,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps) if (qemuCaps->kvmSupportsNesting) virBufferAddLit(&buf, "\n"); + if (qemuCaps->kvmSupportsSecureGuest) + virBufferAddLit(&buf, "\n"); + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "\n"); @@ -4678,6 +4687,49 @@ virQEMUCapsSaveFile(void *data, } +/* + * Check whether IBM Secure Execution (S390) is enabled + */ +static bool +virQEMUCapsKVMSupportsSecureGuestS390(void) +{ + + g_autofree char *cmdline = NULL; + static const char *kValues[] = {"y", "Y", "on", "ON", "oN", "On", "1"}; + + if (!virFileIsDir("/sys/firmware/uv")) + return false; + + if (virFileReadValueString(&cmdline, "/proc/cmdline") < 0) + return false; + + /* we're prefix matching rather than equality matching here, because kernel + * would treat even something like prot_virt='yFOO' as enabled */ + if (virKernelCmdlineMatchParam(cmdline, "prot_virt", kValues, + G_N_ELEMENTS(kValues), + VIR_KERNEL_CMDLINE_FLAGS_SEARCH_FIRST | + VIR_KERNEL_CMDLINE_FLAGS_CMP_PREFIX)) + return true; + + return false; +} + + +/* + * Check whether the secure guest functionality is enabled. + * See the specific architecture function for details on the verifications made. + */ +static bool +virQEMUCapsKVMSupportsSecureGuest(void) +{ + virArch arch = virArchFromHost(); + + if (ARCH_IS_S390(arch)) + return virQEMUCapsKVMSupportsSecureGuestS390(); + return false; +} + + /* Check the kernel module parameters 'nested' file to determine if enabled * * Intel: 'kvm_intel' uses 'Y' @@ -4865,6 +4917,13 @@ virQEMUCapsIsValid(void *data, qemuCaps->binary, qemuCaps->kvmSupportsNesting); return false; } + + if (virQEMUCapsKVMSupportsSecureGuest() != qemuCaps->kvmSupportsSecureGuest) { + VIR_DEBUG("Outdated capabilities for '%s': kvm kernel secure guest " + "value changed from %d", + qemuCaps->binary, qemuCaps->kvmSupportsSecureGuest); + return false; + } } return true; @@ -5366,6 +5425,8 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch, qemuCaps->kernelVersion = g_strdup(kernelVersion); qemuCaps->kvmSupportsNesting = virQEMUCapsKVMSupportsNesting(); + + qemuCaps->kvmSupportsSecureGuest = virQEMUCapsKVMSupportsSecureGuest(); } return qemuCaps;