mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-10-29 17:33:09 +00: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
|
static void
|
||||||
virDomainCapsDispose(void *obj)
|
virDomainCapsDispose(void *obj)
|
||||||
{
|
{
|
||||||
|
@ -137,6 +137,15 @@ struct _virDomainCapsCPU {
|
|||||||
virDomainCapsCPUModelsPtr custom;
|
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 {
|
struct _virDomainCaps {
|
||||||
virObjectLockable parent;
|
virObjectLockable parent;
|
||||||
|
|
||||||
@ -202,4 +211,7 @@ int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
|
|||||||
void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
|
void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
|
||||||
|
|
||||||
char * virDomainCapsFormat(virDomainCapsPtr const caps);
|
char * virDomainCapsFormat(virDomainCapsPtr const caps);
|
||||||
|
|
||||||
|
void
|
||||||
|
virSEVCapabilitiesFree(virSEVCapability *capabilities);
|
||||||
#endif /* __DOMAIN_CAPABILITIES_H__ */
|
#endif /* __DOMAIN_CAPABILITIES_H__ */
|
||||||
|
@ -185,6 +185,7 @@ virDomainCapsEnumClear;
|
|||||||
virDomainCapsEnumSet;
|
virDomainCapsEnumSet;
|
||||||
virDomainCapsFormat;
|
virDomainCapsFormat;
|
||||||
virDomainCapsNew;
|
virDomainCapsNew;
|
||||||
|
virSEVCapabilitiesFree;
|
||||||
|
|
||||||
|
|
||||||
# conf/domain_conf.h
|
# conf/domain_conf.h
|
||||||
|
@ -497,6 +497,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
|
|||||||
"tpm-emulator",
|
"tpm-emulator",
|
||||||
"mch",
|
"mch",
|
||||||
"mch.extended-tseg-mbytes",
|
"mch.extended-tseg-mbytes",
|
||||||
|
|
||||||
|
/* 310 */
|
||||||
|
"sev-guest",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -563,6 +566,8 @@ struct _virQEMUCaps {
|
|||||||
size_t ngicCapabilities;
|
size_t ngicCapabilities;
|
||||||
virGICCapability *gicCapabilities;
|
virGICCapability *gicCapabilities;
|
||||||
|
|
||||||
|
virSEVCapability *sevCapabilities;
|
||||||
|
|
||||||
virQEMUCapsHostCPUData kvmCPU;
|
virQEMUCapsHostCPUData kvmCPU;
|
||||||
virQEMUCapsHostCPUData tcgCPU;
|
virQEMUCapsHostCPUData tcgCPU;
|
||||||
};
|
};
|
||||||
@ -1135,6 +1140,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
|
|||||||
{ "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
|
{ "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
|
||||||
{ "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
|
{ "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
|
||||||
{ "mch", QEMU_CAPS_DEVICE_MCH },
|
{ "mch", QEMU_CAPS_DEVICE_MCH },
|
||||||
|
{ "sev-guest", QEMU_CAPS_SEV_GUEST },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
|
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
|
static int
|
||||||
virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
|
virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
|
||||||
qemuMonitorPtr mon)
|
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
|
bool
|
||||||
virQEMUCapsCPUFilterFeatures(const char *name,
|
virQEMUCapsCPUFilterFeatures(const char *name,
|
||||||
void *opaque)
|
void *opaque)
|
||||||
@ -4064,6 +4095,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
|
|||||||
virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
|
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;
|
ret = 0;
|
||||||
cleanup:
|
cleanup:
|
||||||
return ret;
|
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_DEVICE_MCH, /* Northbridge in q35 machine types */
|
||||||
QEMU_CAPS_MCH_EXTENDED_TSEG_MBYTES, /* -global mch.extended-tseg-mbytes */
|
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 */
|
QEMU_CAPS_LAST /* this must always be the last item */
|
||||||
} virQEMUCapsFlags;
|
} virQEMUCapsFlags;
|
||||||
|
|
||||||
@ -615,5 +618,4 @@ bool virQEMUCapsGuestIsNative(virArch host,
|
|||||||
|
|
||||||
bool virQEMUCapsCPUFilterFeatures(const char *name,
|
bool virQEMUCapsCPUFilterFeatures(const char *name,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
#endif /* __QEMU_CAPABILITIES_H__*/
|
#endif /* __QEMU_CAPABILITIES_H__*/
|
||||||
|
@ -90,6 +90,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
|
|||||||
virGICCapability *capabilities,
|
virGICCapability *capabilities,
|
||||||
size_t ncapabilities);
|
size_t ncapabilities);
|
||||||
|
|
||||||
|
void
|
||||||
|
virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
|
||||||
|
virSEVCapability *capabilities);
|
||||||
|
|
||||||
int
|
int
|
||||||
virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
|
virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
|
||||||
qemuMonitorPtr mon,
|
qemuMonitorPtr mon,
|
||||||
|
@ -3849,6 +3849,16 @@ qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
|
||||||
|
virSEVCapability **capabilities)
|
||||||
|
{
|
||||||
|
QEMU_CHECK_MONITOR(mon);
|
||||||
|
|
||||||
|
return qemuMonitorJSONGetSEVCapabilities(mon, capabilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
qemuMonitorNBDServerStart(qemuMonitorPtr mon,
|
qemuMonitorNBDServerStart(qemuMonitorPtr mon,
|
||||||
const char *host,
|
const char *host,
|
||||||
|
@ -711,6 +711,9 @@ int qemuMonitorSetMigrationCapabilities(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
|
||||||
virGICCapability **capabilities);
|
virGICCapability **capabilities);
|
||||||
|
|
||||||
|
int qemuMonitorGetSEVCapabilities(qemuMonitorPtr mon,
|
||||||
|
virSEVCapability **capabilities);
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QEMU_MONITOR_MIGRATE_BACKGROUND = 1 << 0,
|
QEMU_MONITOR_MIGRATE_BACKGROUND = 1 << 0,
|
||||||
QEMU_MONITOR_MIGRATE_NON_SHARED_DISK = 1 << 1, /* migration with non-shared storage with full disk copy */
|
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;
|
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
|
static virJSONValuePtr
|
||||||
qemuMonitorJSONBuildInetSocketAddress(const char *host,
|
qemuMonitorJSONBuildInetSocketAddress(const char *host,
|
||||||
const char *port)
|
const char *port)
|
||||||
|
@ -152,6 +152,9 @@ int qemuMonitorJSONSetMigrationCapabilities(qemuMonitorPtr mon,
|
|||||||
int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
|
int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
|
||||||
virGICCapability **capabilities);
|
virGICCapability **capabilities);
|
||||||
|
|
||||||
|
int qemuMonitorJSONGetSEVCapabilities(qemuMonitorPtr mon,
|
||||||
|
virSEVCapability **capabilities);
|
||||||
|
|
||||||
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
|
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
|
||||||
unsigned int flags,
|
unsigned int flags,
|
||||||
const char *uri);
|
const char *uri);
|
||||||
|
@ -19038,6 +19038,16 @@
|
|||||||
"id": "libvirt-52"
|
"id": "libvirt-52"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"return" : {
|
||||||
|
"reduced-phys-bits": 1,
|
||||||
|
"cbitpos": 47,
|
||||||
|
"cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
|
||||||
|
"pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
|
||||||
|
},
|
||||||
|
"id": "libvirt-52"
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
"return": {
|
"return": {
|
||||||
},
|
},
|
||||||
|
@ -210,9 +210,10 @@
|
|||||||
<flag name='tpm-emulator'/>
|
<flag name='tpm-emulator'/>
|
||||||
<flag name='mch'/>
|
<flag name='mch'/>
|
||||||
<flag name='mch.extended-tseg-mbytes'/>
|
<flag name='mch.extended-tseg-mbytes'/>
|
||||||
|
<flag name='sev-guest'/>
|
||||||
<version>2011090</version>
|
<version>2011090</version>
|
||||||
<kvmVersion>0</kvmVersion>
|
<kvmVersion>0</kvmVersion>
|
||||||
<microcodeVersion>391586</microcodeVersion>
|
<microcodeVersion>391832</microcodeVersion>
|
||||||
<package>v2.12.0-rc0</package>
|
<package>v2.12.0-rc0</package>
|
||||||
<arch>x86_64</arch>
|
<arch>x86_64</arch>
|
||||||
<hostCPU type='kvm' model='base' migratability='yes'>
|
<hostCPU type='kvm' model='base' migratability='yes'>
|
||||||
|
Loading…
Reference in New Issue
Block a user