mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-09 01:18:00 +03:00
qemu: Provide support to query the SEV capability
QEMU version >= 2.12 provides support for launching an encrypted VMs on AMD x86 platform using Secure Encrypted Virtualization (SEV) feature. This patch adds support to query the SEV capability from the qemu. Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
2cbdf303dd
commit
d4005609f3
@ -67,6 +67,18 @@ virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr values)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virSEVCapabilitiesFree(virSEVCapability *cap)
|
||||
{
|
||||
if (!cap)
|
||||
return;
|
||||
|
||||
VIR_FREE(cap->pdh);
|
||||
VIR_FREE(cap->cert_chain);
|
||||
VIR_FREE(cap);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virDomainCapsDispose(void *obj)
|
||||
{
|
||||
|
@ -137,6 +137,15 @@ struct _virDomainCapsCPU {
|
||||
virDomainCapsCPUModelsPtr custom;
|
||||
};
|
||||
|
||||
typedef struct _virSEVCapability virSEVCapability;
|
||||
typedef virSEVCapability *virSEVCapabilityPtr;
|
||||
struct _virSEVCapability {
|
||||
char *pdh;
|
||||
char *cert_chain;
|
||||
unsigned int cbitpos;
|
||||
unsigned int reduced_phys_bits;
|
||||
};
|
||||
|
||||
struct _virDomainCaps {
|
||||
virObjectLockable parent;
|
||||
|
||||
@ -202,4 +211,7 @@ int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
|
||||
void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
|
||||
|
||||
char * virDomainCapsFormat(virDomainCapsPtr const caps);
|
||||
|
||||
void
|
||||
virSEVCapabilitiesFree(virSEVCapability *capabilities);
|
||||
#endif /* __DOMAIN_CAPABILITIES_H__ */
|
||||
|
@ -185,6 +185,7 @@ virDomainCapsEnumClear;
|
||||
virDomainCapsEnumSet;
|
||||
virDomainCapsFormat;
|
||||
virDomainCapsNew;
|
||||
virSEVCapabilitiesFree;
|
||||
|
||||
|
||||
# conf/domain_conf.h
|
||||
|
@ -497,6 +497,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
|
||||
"tpm-emulator",
|
||||
"mch",
|
||||
"mch.extended-tseg-mbytes",
|
||||
|
||||
/* 310 */
|
||||
"sev-guest",
|
||||
);
|
||||
|
||||
|
||||
@ -563,6 +566,8 @@ struct _virQEMUCaps {
|
||||
size_t ngicCapabilities;
|
||||
virGICCapability *gicCapabilities;
|
||||
|
||||
virSEVCapability *sevCapabilities;
|
||||
|
||||
virQEMUCapsHostCPUData kvmCPU;
|
||||
virQEMUCapsHostCPUData tcgCPU;
|
||||
};
|
||||
@ -1135,6 +1140,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
|
||||
{ "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
|
||||
{ "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
|
||||
{ "mch", QEMU_CAPS_DEVICE_MCH },
|
||||
{ "sev-guest", QEMU_CAPS_SEV_GUEST },
|
||||
};
|
||||
|
||||
static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
|
||||
@ -2078,6 +2084,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
virSEVCapability *capabilities)
|
||||
{
|
||||
virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
|
||||
|
||||
qemuCaps->sevCapabilities = capabilities;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
|
||||
qemuMonitorPtr mon)
|
||||
@ -2665,6 +2681,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
qemuMonitorPtr mon)
|
||||
{
|
||||
virSEVCapability *caps = NULL;
|
||||
|
||||
if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
|
||||
return -1;
|
||||
|
||||
virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
virQEMUCapsCPUFilterFeatures(const char *name,
|
||||
void *opaque)
|
||||
@ -4064,6 +4095,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
|
||||
virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
|
||||
}
|
||||
|
||||
/* Probe for SEV capabilities */
|
||||
if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
|
||||
if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
|
||||
virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
return ret;
|
||||
|
@ -482,6 +482,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
|
||||
QEMU_CAPS_DEVICE_MCH, /* Northbridge in q35 machine types */
|
||||
QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES, /* -global mch.extended-tseg-mbytes */
|
||||
|
||||
/* 310 */
|
||||
QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
|
||||
|
||||
QEMU_CAPS_LAST /* this must always be the last item */
|
||||
} virQEMUCapsFlags;
|
||||
|
||||
@ -615,5 +618,4 @@ bool virQEMUCapsGuestIsNative(virArch host,
|
||||
|
||||
bool virQEMUCapsCPUFilterFeatures(const char *name,
|
||||
void *opaque);
|
||||
|
||||
#endif /* __QEMU_CAPABILITIES_H__*/
|
||||
|
@ -90,6 +90,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
virGICCapability *capabilities,
|
||||
size_t ncapabilities);
|
||||
|
||||
void
|
||||
virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
|
||||
virSEVCapability *capabilities);
|
||||
|
||||
int
|
||||
virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
|
||||
qemuMonitorPtr mon,
|
||||
|
@ -3849,6 +3849,16 @@ qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
|
||||
virSEVCapability **capabilities)
|
||||
{
|
||||
QEMU_CHECK_MONITOR(mon);
|
||||
|
||||
return qemuMonitorJSONGetSEVCapabilities(mon, capabilities);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorNBDServerStart(qemuMonitorPtr mon,
|
||||
const char *host,
|
||||
|
@ -711,6 +711,9 @@ int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon,
|
||||
int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
||||
virGICCapability **capabilities);
|
||||
|
||||
int qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
|
||||
virSEVCapability **capabilities);
|
||||
|
||||
typedef enum {
|
||||
QEMU_MONITOR_MIGRATE_BACKGROUND = 1 << 0,
|
||||
QEMU_MONITOR_MIGRATE_NON_SHARED_DISK = 1 << 1, /* migration with non-shared storage with full disk copy */
|
||||
|
@ -6401,6 +6401,85 @@ qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
|
||||
virSEVCapability **capabilities)
|
||||
{
|
||||
int ret = -1;
|
||||
virJSONValuePtr cmd;
|
||||
virJSONValuePtr reply = NULL;
|
||||
virJSONValuePtr caps;
|
||||
virSEVCapability *capability = NULL;
|
||||
const char *pdh = NULL, *cert_chain = NULL;
|
||||
unsigned int cbitpos, reduced_phys_bits;
|
||||
|
||||
*capabilities = NULL;
|
||||
|
||||
if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-capabilities",
|
||||
NULL)))
|
||||
return -1;
|
||||
|
||||
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
|
||||
goto cleanup;
|
||||
|
||||
caps = virJSONValueObjectGetObject(reply, "return");
|
||||
|
||||
if (virJSONValueObjectGetNumberUint(caps, "cbitpos", &cbitpos) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-sev-capabilities reply was missing"
|
||||
" 'cbitpos' field"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (virJSONValueObjectGetNumberUint(caps, "reduced-phys-bits",
|
||||
&reduced_phys_bits) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-sev-capabilities reply was missing"
|
||||
" 'reduced-phys-bits' field"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(pdh = virJSONValueObjectGetString(caps, "pdh"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-sev-capabilities reply was missing"
|
||||
" 'pdh' field"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(cert_chain = virJSONValueObjectGetString(caps, "cert-chain"))) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||
_("query-sev-capabilities reply was missing"
|
||||
" 'cert-chain' field"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(capability) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (VIR_STRDUP(capability->pdh, pdh) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (VIR_STRDUP(capability->cert_chain, cert_chain) < 0)
|
||||
goto cleanup;
|
||||
|
||||
capability->cbitpos = cbitpos;
|
||||
capability->reduced_phys_bits = reduced_phys_bits;
|
||||
VIR_STEAL_PTR(*capabilities, capability);
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
virSEVCapabilitiesFree(capability);
|
||||
virJSONValueFree(cmd);
|
||||
virJSONValueFree(reply);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static virJSONValuePtr
|
||||
qemuMonitorJSONBuildInetSocketAddress(const char *host,
|
||||
const char *port)
|
||||
|
@ -152,6 +152,9 @@ int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon,
|
||||
int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
|
||||
virGICCapability **capabilities);
|
||||
|
||||
int qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
|
||||
virSEVCapability **capabilities);
|
||||
|
||||
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
|
||||
unsigned int flags,
|
||||
const char *uri);
|
||||
|
@ -19038,6 +19038,16 @@
|
||||
"id": "libvirt-52"
|
||||
}
|
||||
|
||||
{
|
||||
"return" : {
|
||||
"reduced-phys-bits": 1,
|
||||
"cbitpos": 47,
|
||||
"cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
|
||||
"pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
|
||||
},
|
||||
"id": "libvirt-52"
|
||||
}
|
||||
|
||||
{
|
||||
"return": {
|
||||
},
|
||||
|
@ -210,9 +210,10 @@
|
||||
<flag name='tpm-emulator'/>
|
||||
<flag name='mch'/>
|
||||
<flag name='mch.extended-tseg-mbytes'/>
|
||||
<flag name='sev-guest'/>
|
||||
<version>2011090</version>
|
||||
<kvmVersion>0</kvmVersion>
|
||||
<microcodeVersion>391586</microcodeVersion>
|
||||
<microcodeVersion>391832</microcodeVersion>
|
||||
<package>v2.12.0-rc0</package>
|
||||
<arch>x86_64</arch>
|
||||
<hostCPU type='kvm' model='base' migratability='yes'>
|
||||
|
Loading…
Reference in New Issue
Block a user