Use the query-gic-capabilities QMP command to probe GIC capabilities for a QEMU binary. The information obtained is stored in virQEMUCaps. --- src/qemu/qemu_capabilities.c | 24 ++++++++++++ src/qemu/qemu_monitor.c | 10 +++++ src/qemu/qemu_monitor.h | 4 ++ src/qemu/qemu_monitor_json.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 4 ++ src/util/virgic.h | 13 +++++++ 6 files changed, 145 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4b1e750..e54208a 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -354,6 +354,9 @@ struct _virQEMUCaps { char **machineTypes; char **machineAliases; unsigned int *machineMaxCpus; + + size_t ngicCapabilities; + virGICCapability *gicCapabilities; }; struct virQEMUCapsSearchData { @@ -2690,6 +2693,22 @@ virQEMUCapsProbeQMPMigrationCapabilities(virQEMUCapsPtr qemuCaps, return 0; } +static int +virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr qemuCaps, + qemuMonitorPtr mon) +{ + virGICCapability *caps = NULL; + int ncaps; + + if ((ncaps = qemuMonitorGetGICCapabilities(mon, &caps)) < 0) + return -1; + + qemuCaps->gicCapabilities = caps; + qemuCaps->ngicCapabilities = ncaps; + + return 0; +} + int virQEMUCapsProbeQMP(virQEMUCapsPtr qemuCaps, qemuMonitorPtr mon) { @@ -3410,6 +3429,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (virQEMUCapsProbeQMPMigrationCapabilities(qemuCaps, mon) < 0) goto cleanup; + /* GIC capabilities, eg. available GIC versions */ + if (ARCH_IS_ARM(qemuCaps->arch) && + virQEMUCapsProbeQMPGICCapabilities(qemuCaps, mon) < 0) + goto cleanup; + ret = 0; cleanup: return ret; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index ace3bb4..ac5fe8c 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3552,6 +3552,16 @@ qemuMonitorSetMigrationCapability(qemuMonitorPtr mon, int +qemuMonitorGetGICCapabilities(qemuMonitorPtr mon, + virGICCapability **capabilities) +{ + QEMU_CHECK_MONITOR_JSON(mon); + + return qemuMonitorJSONGetGICCapabilities(mon, capabilities); +} + + +int qemuMonitorNBDServerStart(qemuMonitorPtr mon, const char *host, unsigned int port) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 4467a41..550eae0 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -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; @@ -545,6 +546,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 */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8352e53..dee2ee4 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5744,6 +5744,96 @@ qemuMonitorJSONSetMigrationCapability(qemuMonitorPtr mon, return ret; } +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 (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 (VIR_ALLOC_N(list, n + 1) < 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) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 4068187..09a8269 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -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, @@ -137,6 +138,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); diff --git a/src/util/virgic.h b/src/util/virgic.h index 470ce95..1c9efd6 100644 --- a/src/util/virgic.h +++ b/src/util/virgic.h @@ -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__ */ -- 2.5.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list