提交 12209ba5 编写于 作者: A Andrea Bolognani

qemu: Probe GIC capabilities

QEMU introduced the query-gic-capabilities QMP command
with commit 4468d4e0f383: use the command, if available,
to probe available GIC capabilities.

The information obtained is stored in a virQEMUCaps
instance, and will be later used to fill in a
virDomainCaps instance.
上级 29980231
......@@ -358,6 +358,9 @@ struct _virQEMUCaps {
char **machineTypes;
char **machineAliases;
unsigned int *machineMaxCpus;
size_t ngicCapabilities;
virGICCapability *gicCapabilities;
};
struct virQEMUCapsSearchData {
......@@ -2082,6 +2085,8 @@ void virQEMUCapsDispose(void *obj)
VIR_FREE(qemuCaps->package);
VIR_FREE(qemuCaps->binary);
VIR_FREE(qemuCaps->gicCapabilities);
}
void
......@@ -2696,6 +2701,34 @@ virQEMUCapsProbeQMPMigrationCapabilities(virQEMUCapsPtr qemuCaps,
return 0;
}
/**
* virQEMUCapsProbeQMPGICCapabilities:
* @qemuCaps: QEMU binary capabilities
* @mon: QEMU monitor
*
* Use @mon to obtain information about the GIC capabilities for the
* corresponding QEMU binary, and store them in @qemuCaps.
*
* Returns: 0 on success, <0 on failure
*/
static int
virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr qemuCaps,
qemuMonitorPtr mon)
{
virGICCapability *caps = NULL;
int ncaps;
if ((ncaps = qemuMonitorGetGICCapabilities(mon, &caps)) < 0)
return -1;
VIR_FREE(qemuCaps->gicCapabilities);
qemuCaps->gicCapabilities = caps;
qemuCaps->ngicCapabilities = ncaps;
return 0;
}
int virQEMUCapsProbeQMP(virQEMUCapsPtr qemuCaps,
qemuMonitorPtr mon)
{
......@@ -3047,6 +3080,9 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps)
VIR_FREE(qemuCaps->machineAliases);
VIR_FREE(qemuCaps->machineMaxCpus);
qemuCaps->nmachineTypes = 0;
VIR_FREE(qemuCaps->gicCapabilities);
qemuCaps->ngicCapabilities = 0;
}
......@@ -3411,6 +3447,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
if (virQEMUCapsProbeQMPMigrationCapabilities(qemuCaps, mon) < 0)
goto cleanup;
/* GIC capabilities, eg. available GIC versions */
if ((qemuCaps->arch == VIR_ARCH_AARCH64 ||
qemuCaps->arch == VIR_ARCH_ARMV7L) &&
virQEMUCapsProbeQMPGICCapabilities(qemuCaps, mon) < 0)
goto cleanup;
ret = 0;
cleanup:
return ret;
......
......@@ -3582,6 +3582,23 @@ qemuMonitorSetMigrationCapability(qemuMonitorPtr mon,
}
/**
* qemuMonitorGetGICCapabilities:
* @mon: QEMU monitor
* @capabilities: where to store the GIC capabilities
*
* See qemuMonitorJSONGetGICCapabilities().
*/
int
qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
virGICCapability **capabilities)
{
QEMU_CHECK_MONITOR_JSON(mon);
return qemuMonitorJSONGetGICCapabilities(mon, capabilities);
}
int
qemuMonitorNBDServerStart(qemuMonitorPtr mon,
const char *host,
......
......@@ -34,6 +34,7 @@
# include "virnetdev.h"
# include "device_conf.h"
# include "cpu/cpu.h"
# include "util/virgic.h"
typedef struct _qemuMonitor qemuMonitor;
typedef qemuMonitor *qemuMonitorPtr;
......@@ -583,6 +584,9 @@ int qemuMonitorSetMigrationCapability(qemuMonitorPtr mon,
qemuMonitorMigrationCaps capability,
bool state);
int qemuMonitorGetGICCapabilities(qemuMonitorPtr mon,
virGICCapability **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 */
......
......@@ -5855,6 +5855,121 @@ qemuMonitorJSONSetMigrationCapability(qemuMonitorPtr mon,
return ret;
}
/**
* qemuMonitorJSONGetGICCapabilities:
* @mon: QEMU JSON monitor
* @capabilities: where to store the GIC capabilities
*
* Use @mon to obtain information about the GIC capabilities for the
* corresponding QEMU binary, and store them in @capabilities.
*
* If the QEMU binary has no GIC capabilities, or if GIC capabilities could
* not be determined due to the lack of 'query-gic-capabilities' QMP command,
* a NULL pointer will be returned instead of an empty array.
*
* Returns: the number of GIC capabilities obtained from the monitor,
* <0 on failure
*/
int
qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
virGICCapability **capabilities)
{
int ret;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
virJSONValuePtr caps;
virGICCapability *list = NULL;
size_t i;
ssize_t n;
*capabilities = NULL;
if (!(cmd = qemuMonitorJSONMakeCommand("query-gic-capabilities",
NULL)))
return -1;
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
if (ret == 0) {
/* If the 'query-gic-capabilities' QMP command was not available
* we simply successfully return zero capabilities.
* This is the case for QEMU <2.6 and all non-ARM architectures */
if (qemuMonitorJSONHasError(reply, "CommandNotFound"))
goto cleanup;
ret = qemuMonitorJSONCheckError(cmd, reply);
}
if (ret < 0)
goto cleanup;
ret = -1;
if (!(caps = virJSONValueObjectGetArray(reply, "return")) ||
(n = virJSONValueArraySize(caps)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing GIC capabilities"));
goto cleanup;
}
/* If the returned array was empty we have to return successfully */
if (n == 0) {
ret = 0;
goto cleanup;
}
if (VIR_ALLOC_N(list, n) < 0)
goto cleanup;
for (i = 0; i < n; i++) {
virJSONValuePtr cap = virJSONValueArrayGet(caps, i);
int version;
bool kernel;
bool emulated;
if (!cap || cap->type != VIR_JSON_TYPE_OBJECT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing entry in GIC capabilities list"));
goto cleanup;
}
if (virJSONValueObjectGetNumberInt(cap, "version", &version) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing GIC version"));
goto cleanup;
}
if (virJSONValueObjectGetBoolean(cap, "kernel", &kernel) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing in-kernel GIC information"));
goto cleanup;
}
if (virJSONValueObjectGetBoolean(cap, "emulated", &emulated) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("missing emulated GIC information"));
goto cleanup;
}
list[i].version = version;
if (kernel)
list[i].implementation |= VIR_GIC_IMPLEMENTATION_KERNEL;
if (emulated)
list[i].implementation |= VIR_GIC_IMPLEMENTATION_EMULATED;
}
ret = n;
*capabilities = list;
cleanup:
if (ret < 0)
VIR_FREE(list);
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
static virJSONValuePtr
qemuMonitorJSONBuildInetSocketAddress(const char *host,
const char *port)
......
......@@ -30,6 +30,7 @@
# include "qemu_monitor.h"
# include "virbitmap.h"
# include "cpu/cpu.h"
# include "util/virgic.h"
int qemuMonitorJSONIOProcess(qemuMonitorPtr mon,
const char *data,
......@@ -142,6 +143,9 @@ int qemuMonitorJSONSetMigrationCapability(qemuMonitorPtr mon,
qemuMonitorMigrationCaps capability,
bool state);
int qemuMonitorJSONGetGICCapabilities(qemuMonitorPtr mon,
virGICCapability **capabilities);
int qemuMonitorJSONMigrate(qemuMonitorPtr mon,
unsigned int flags,
const char *uri);
......
......@@ -38,4 +38,17 @@ VIR_ENUM_DECL(virGICVersion);
/* Consider GIC v2 the default */
# define VIR_GIC_VERSION_DEFAULT VIR_GIC_VERSION_2
typedef enum {
VIR_GIC_IMPLEMENTATION_NONE = 0,
VIR_GIC_IMPLEMENTATION_KERNEL = (1 << 1),
VIR_GIC_IMPLEMENTATION_EMULATED = (1 << 2)
} virGICImplementation;
typedef struct _virGICCapability virGICCapability;
typedef virGICCapability *virGICCapabilityPtr;
struct _virGICCapability {
virGICVersion version;
virGICImplementation implementation;
};
#endif /* __VIR_GIC_H__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册