[libvirt] [PATCH 0/7] Probe and expose GIC capabilities

Changes from [RFC]: * Fix issues pointed out during review (see patches 1 and 2 for details) * Add documentation The only thing missing AFAIK is some test cases... I'm not sure whether it's possible to include QMP replies for QEMU 2.6 even though it hasn't been released yet, and I wouldn't know how to generate a .replies file anyway. Any pointers? Cheers. [RFC] https://www.redhat.com/archives/libvir-list/2016-March/msg00956.html Andrea Bolognani (7): conf: Get rid of virDomainCapsDevice qemu: Probe GIC capabilities schema: Validate GIC capabilities conf: Expose GIC capabilities qemu: Fill in GIC capabilities qemu: Cache GIC capabilities docs: Document the new XML elements docs/formatdomain.html.in | 3 +- docs/formatdomaincaps.html.in | 43 ++++- docs/schemas/domaincaps.rng | 18 ++ src/conf/domain_capabilities.c | 42 ++++- src/conf/domain_capabilities.h | 24 +-- src/qemu/qemu_capabilities.c | 194 ++++++++++++++++++++- src/qemu/qemu_monitor.c | 17 ++ src/qemu/qemu_monitor.h | 4 + src/qemu/qemu_monitor_json.c | 115 ++++++++++++ src/qemu/qemu_monitor_json.h | 4 + src/util/virgic.h | 13 ++ tests/domaincapsschemadata/domaincaps-basic.xml | 3 + tests/domaincapsschemadata/domaincaps-full.xml | 3 + .../domaincaps-qemu_1.6.50-1.xml | 3 + tests/domaincapstest.c | 8 +- 15 files changed, 470 insertions(+), 24 deletions(-) -- 2.5.5

The struct contains a single boolean field, 'supported': the meaning of this field is too generic to be limited to devices only, and in fact it's already being used for other things like loaders and OSs. Instead of trying to come up with a more generic name just get rid of the struct altogether. --- Changes from RFC: * Improve commit message src/conf/domain_capabilities.c | 6 +++--- src/conf/domain_capabilities.h | 14 ++++---------- src/qemu/qemu_capabilities.c | 8 ++++---- tests/domaincapstest.c | 8 ++++---- 4 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 0e32f52..466c0c6 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -187,9 +187,9 @@ virDomainCapsStringValuesFormat(virBufferPtr buf, #define FORMAT_PROLOGUE(item) \ do { \ virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \ - item->device.supported ? "yes" : "no", \ - item->device.supported ? ">" : "/>"); \ - if (!item->device.supported) \ + item->supported ? "yes" : "no", \ + item->supported ? ">" : "/>"); \ + if (!item->supported) \ return; \ virBufferAdjustIndent(buf, 2); \ } while (0) diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 597ac75..3eacb35 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -44,16 +44,10 @@ struct _virDomainCapsStringValues { size_t nvalues; /* number of strings */ }; -typedef struct _virDomainCapsDevice virDomainCapsDevice; -typedef virDomainCapsDevice *virDomainCapsDevicePtr; -struct _virDomainCapsDevice { - bool supported; /* true if <devtype> is supported by hypervisor */ -}; - typedef struct _virDomainCapsLoader virDomainCapsLoader; typedef virDomainCapsLoader *virDomainCapsLoaderPtr; struct _virDomainCapsLoader { - virDomainCapsDevice device; + bool supported; virDomainCapsStringValues values; /* Info about values for the element */ virDomainCapsEnum type; /* Info about virDomainLoader */ virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */ @@ -62,14 +56,14 @@ struct _virDomainCapsLoader { typedef struct _virDomainCapsOS virDomainCapsOS; typedef virDomainCapsOS *virDomainCapsOSPtr; struct _virDomainCapsOS { - virDomainCapsDevice device; + bool supported; virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ }; typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk; typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; struct _virDomainCapsDeviceDisk { - virDomainCapsDevice device; + bool supported; virDomainCapsEnum diskDevice; /* Info about virDomainDiskDevice enum values */ virDomainCapsEnum bus; /* Info about virDomainDiskBus enum values */ /* add new fields here */ @@ -78,7 +72,7 @@ struct _virDomainCapsDeviceDisk { typedef struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev; typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr; struct _virDomainCapsDeviceHostdev { - virDomainCapsDevice device; + bool supported; virDomainCapsEnum mode; /* Info about virDomainHostdevMode */ virDomainCapsEnum startupPolicy; /* Info about virDomainStartupPolicy */ virDomainCapsEnum subsysType; /* Info about virDomainHostdevSubsysType */ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f46dcad..9ae7b27 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3908,7 +3908,7 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, { size_t i; - capsLoader->device.supported = true; + capsLoader->supported = true; if (VIR_ALLOC_N(capsLoader->values.values, nloader) < 0) return -1; @@ -3950,7 +3950,7 @@ virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, { virDomainCapsLoaderPtr capsLoader = &os->loader; - os->device.supported = true; + os->supported = true; if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, capsLoader, loader, nloader) < 0) return -1; @@ -3963,7 +3963,7 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, const char *machine, virDomainCapsDeviceDiskPtr disk) { - disk->device.supported = true; + disk->supported = true; /* QEMU supports all of these */ VIR_DOMAIN_CAPS_ENUM_SET(disk->diskDevice, VIR_DOMAIN_DISK_DEVICE_DISK, @@ -3999,7 +3999,7 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy(); bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO(); - hostdev->device.supported = true; + hostdev->supported = true; /* VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES is for containers only */ VIR_DOMAIN_CAPS_ENUM_SET(hostdev->mode, VIR_DOMAIN_HOSTDEV_MODE_SUBSYS); diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index ecefdb9..b6f6ac8 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -65,9 +65,9 @@ fillAll(virDomainCapsPtr domCaps, virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; domCaps->maxvcpus = 255; - os->device.supported = true; + os->supported = true; - loader->device.supported = true; + loader->supported = true; SET_ALL_BITS(loader->type); SET_ALL_BITS(loader->readonly); if (fillStringValues(&loader->values, @@ -76,11 +76,11 @@ fillAll(virDomainCapsPtr domCaps, NULL) < 0) return -1; - disk->device.supported = true; + disk->supported = true; SET_ALL_BITS(disk->diskDevice); SET_ALL_BITS(disk->bus); - hostdev->device.supported = true; + hostdev->supported = true; SET_ALL_BITS(hostdev->mode); SET_ALL_BITS(hostdev->startupPolicy); SET_ALL_BITS(hostdev->subsysType); -- 2.5.5

On 04/18/2016 01:43 PM, Andrea Bolognani wrote:
The struct contains a single boolean field, 'supported': the meaning of this field is too generic to be limited to devices only, and in fact it's already being used for other things like loaders and OSs.
Instead of trying to come up with a more generic name just get rid of the struct altogether. --- Changes from RFC:
* Improve commit message
src/conf/domain_capabilities.c | 6 +++--- src/conf/domain_capabilities.h | 14 ++++---------- src/qemu/qemu_capabilities.c | 8 ++++---- tests/domaincapstest.c | 8 ++++---- 4 files changed, 15 insertions(+), 21 deletions(-)
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 0e32f52..466c0c6 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -187,9 +187,9 @@ virDomainCapsStringValuesFormat(virBufferPtr buf, #define FORMAT_PROLOGUE(item) \ do { \ virBufferAsprintf(buf, "<" #item " supported='%s'%s\n", \ - item->device.supported ? "yes" : "no", \ - item->device.supported ? ">" : "/>"); \ - if (!item->device.supported) \ + item->supported ? "yes" : "no", \ + item->supported ? ">" : "/>"); \ + if (!item->supported) \ return; \ virBufferAdjustIndent(buf, 2); \ } while (0) diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 597ac75..3eacb35 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -44,16 +44,10 @@ struct _virDomainCapsStringValues { size_t nvalues; /* number of strings */ };
-typedef struct _virDomainCapsDevice virDomainCapsDevice; -typedef virDomainCapsDevice *virDomainCapsDevicePtr; -struct _virDomainCapsDevice { - bool supported; /* true if <devtype> is supported by hypervisor */ -}; - typedef struct _virDomainCapsLoader virDomainCapsLoader; typedef virDomainCapsLoader *virDomainCapsLoaderPtr; struct _virDomainCapsLoader { - virDomainCapsDevice device; + bool supported; virDomainCapsStringValues values; /* Info about values for the element */ virDomainCapsEnum type; /* Info about virDomainLoader */ virDomainCapsEnum readonly; /* Info about readonly:virTristateBool */ @@ -62,14 +56,14 @@ struct _virDomainCapsLoader { typedef struct _virDomainCapsOS virDomainCapsOS; typedef virDomainCapsOS *virDomainCapsOSPtr; struct _virDomainCapsOS { - virDomainCapsDevice device; + bool supported; virDomainCapsLoader loader; /* Info about virDomainLoaderDef */ };
typedef struct _virDomainCapsDeviceDisk virDomainCapsDeviceDisk; typedef virDomainCapsDeviceDisk *virDomainCapsDeviceDiskPtr; struct _virDomainCapsDeviceDisk { - virDomainCapsDevice device; + bool supported; virDomainCapsEnum diskDevice; /* Info about virDomainDiskDevice enum values */ virDomainCapsEnum bus; /* Info about virDomainDiskBus enum values */ /* add new fields here */ @@ -78,7 +72,7 @@ struct _virDomainCapsDeviceDisk { typedef struct _virDomainCapsDeviceHostdev virDomainCapsDeviceHostdev; typedef virDomainCapsDeviceHostdev *virDomainCapsDeviceHostdevPtr; struct _virDomainCapsDeviceHostdev { - virDomainCapsDevice device; + bool supported; virDomainCapsEnum mode; /* Info about virDomainHostdevMode */ virDomainCapsEnum startupPolicy; /* Info about virDomainStartupPolicy */ virDomainCapsEnum subsysType; /* Info about virDomainHostdevSubsysType */ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index f46dcad..9ae7b27 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3908,7 +3908,7 @@ virQEMUCapsFillDomainLoaderCaps(virQEMUCapsPtr qemuCaps, { size_t i;
- capsLoader->device.supported = true; + capsLoader->supported = true;
if (VIR_ALLOC_N(capsLoader->values.values, nloader) < 0) return -1; @@ -3950,7 +3950,7 @@ virQEMUCapsFillDomainOSCaps(virQEMUCapsPtr qemuCaps, { virDomainCapsLoaderPtr capsLoader = &os->loader;
- os->device.supported = true; + os->supported = true; if (virQEMUCapsFillDomainLoaderCaps(qemuCaps, capsLoader, loader, nloader) < 0) return -1; @@ -3963,7 +3963,7 @@ virQEMUCapsFillDomainDeviceDiskCaps(virQEMUCapsPtr qemuCaps, const char *machine, virDomainCapsDeviceDiskPtr disk) { - disk->device.supported = true; + disk->supported = true; /* QEMU supports all of these */ VIR_DOMAIN_CAPS_ENUM_SET(disk->diskDevice, VIR_DOMAIN_DISK_DEVICE_DISK, @@ -3999,7 +3999,7 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, bool supportsPassthroughKVM = qemuHostdevHostSupportsPassthroughLegacy(); bool supportsPassthroughVFIO = qemuHostdevHostSupportsPassthroughVFIO();
- hostdev->device.supported = true; + hostdev->supported = true; /* VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES is for containers only */ VIR_DOMAIN_CAPS_ENUM_SET(hostdev->mode, VIR_DOMAIN_HOSTDEV_MODE_SUBSYS); diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index ecefdb9..b6f6ac8 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -65,9 +65,9 @@ fillAll(virDomainCapsPtr domCaps, virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev; domCaps->maxvcpus = 255;
- os->device.supported = true; + os->supported = true;
- loader->device.supported = true; + loader->supported = true; SET_ALL_BITS(loader->type); SET_ALL_BITS(loader->readonly); if (fillStringValues(&loader->values, @@ -76,11 +76,11 @@ fillAll(virDomainCapsPtr domCaps, NULL) < 0) return -1;
- disk->device.supported = true; + disk->supported = true; SET_ALL_BITS(disk->diskDevice); SET_ALL_BITS(disk->bus);
- hostdev->device.supported = true; + hostdev->supported = true; SET_ALL_BITS(hostdev->mode); SET_ALL_BITS(hostdev->startupPolicy); SET_ALL_BITS(hostdev->subsysType);
This looks fine to me. I know John was concerned that maybe this was undoing some intentional arrangement, but I agree with your previous comments that this pattern isn't going to fit the ideal GIC extensions anyways. Plus this is just small internal handling so it can always be changed or generalized differently later if needed ACK - Cole

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. --- Changes from RFC: * Free qemuCaps->gicCapabilities when needed * Always return NULL when no capabilities have been found * Don't allocate (n+1) elements to store (n) capabilities * Check for ARM consistently with the rest of the code * Reference QEMU commit * Leave two empty lines between functions * Document all functions src/qemu/qemu_capabilities.c | 42 ++++++++++++++++ src/qemu/qemu_monitor.c | 17 +++++++ src/qemu/qemu_monitor.h | 4 ++ src/qemu/qemu_monitor_json.c | 115 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 4 ++ src/util/virgic.h | 13 +++++ 6 files changed, 195 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 9ae7b27..4afc6b6 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -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; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 83551a8..7c9ea71 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3580,6 +3580,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, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index bd5d006..470c729 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; @@ -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 */ diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 29d6c8c..7bb9976 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -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) diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 5cbee1a..8b5d422 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, @@ -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); 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

On 04/18/2016 01:43 PM, Andrea Bolognani wrote:
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. --- Changes from RFC:
* Free qemuCaps->gicCapabilities when needed
* Always return NULL when no capabilities have been found
* Don't allocate (n+1) elements to store (n) capabilities
* Check for ARM consistently with the rest of the code
* Reference QEMU commit
* Leave two empty lines between functions
* Document all functions
src/qemu/qemu_capabilities.c | 42 ++++++++++++++++ src/qemu/qemu_monitor.c | 17 +++++++ src/qemu/qemu_monitor.h | 4 ++ src/qemu/qemu_monitor_json.c | 115 +++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 4 ++ src/util/virgic.h | 13 +++++ 6 files changed, 195 insertions(+)
ACK - Cole

We need to expose GIC capabilities in the domain capabilities XML: update the schema to validate documents that contain the new information. --- docs/schemas/domaincaps.rng | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 35d3745..0d2777b 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -31,6 +31,9 @@ <optional> <ref name='devices'/> </optional> + <optional> + <ref name='features'/> + </optional> </interleave> </element> </define> @@ -88,6 +91,21 @@ </element> </define> + <define name='features'> + <element name='features'> + <interleave> + <ref name='gic'/> + </interleave> + </element> + </define> + + <define name='gic'> + <element name='gic'> + <ref name='supported'/> + <ref name='enum'/> + </element> + </define> + <define name='value'> <zeroOrMore> <element name='value'> -- 2.5.5

On 04/18/2016 01:43 PM, Andrea Bolognani wrote:
We need to expose GIC capabilities in the domain capabilities XML: update the schema to validate documents that contain the new information. --- docs/schemas/domaincaps.rng | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
ACK - Cole

Add information about GIC capabilities to virDomainCaps and update the formatter to include them in the XML output. --- src/conf/domain_capabilities.c | 36 ++++++++++++++++++++++ src/conf/domain_capabilities.h | 10 ++++++ tests/domaincapsschemadata/domaincaps-basic.xml | 3 ++ tests/domaincapsschemadata/domaincaps-full.xml | 3 ++ .../domaincaps-qemu_1.6.50-1.xml | 3 ++ 5 files changed, 55 insertions(+) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 466c0c6..eb880ae 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -262,6 +262,34 @@ virDomainCapsDeviceHostdevFormat(virBufferPtr buf, } +/** + * virDomainCapsFeatureGICFormat: + * @buf: target buffer + * @gic: GIC features + * + * Format GIC features for inclusion in the domcapabilities XML. + * + * The resulting XML will look like + * + * <gic supported='yes'> + * <enum name='version> + * <value>2</value> + * <value>3</value> + * </enum> + * </gic> + */ +static void +virDomainCapsFeatureGICFormat(virBufferPtr buf, + virDomainCapsFeatureGICPtr const gic) +{ + FORMAT_PROLOGUE(gic); + + ENUM_PROCESS(gic, version, virGICVersionTypeToString); + + FORMAT_EPILOGUE(gic); +} + + static int virDomainCapsFormatInternal(virBufferPtr buf, virDomainCapsPtr const caps) @@ -291,6 +319,14 @@ virDomainCapsFormatInternal(virBufferPtr buf, virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</devices>\n"); + virBufferAddLit(buf, "<features>\n"); + virBufferAdjustIndent(buf, 2); + + virDomainCapsFeatureGICFormat(buf, &caps->gic); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</features>\n"); + virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</domainCapabilities>\n"); return 0; diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 3eacb35..95afe5e 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -81,6 +81,13 @@ struct _virDomainCapsDeviceHostdev { /* add new fields here */ }; +typedef struct _virDomainCapsFeatureGIC virDomainCapsFeatureGIC; +typedef virDomainCapsFeatureGIC *virDomainCapsFeatureGICPtr; +struct _virDomainCapsFeatureGIC { + bool supported; + virDomainCapsEnum version; /* Info about virGICVersion */ +}; + struct _virDomainCaps { virObjectLockable parent; @@ -96,6 +103,9 @@ struct _virDomainCaps { virDomainCapsDeviceDisk disk; virDomainCapsDeviceHostdev hostdev; /* add new domain devices here */ + + virDomainCapsFeatureGIC gic; + /* add new domain features here */ }; virDomainCapsPtr virDomainCapsNew(const char *path, diff --git a/tests/domaincapsschemadata/domaincaps-basic.xml b/tests/domaincapsschemadata/domaincaps-basic.xml index 6171393..6587d56 100644 --- a/tests/domaincapsschemadata/domaincaps-basic.xml +++ b/tests/domaincapsschemadata/domaincaps-basic.xml @@ -8,4 +8,7 @@ <disk supported='no'/> <hostdev supported='no'/> </devices> + <features> + <gic supported='no'/> + </features> </domainCapabilities> diff --git a/tests/domaincapsschemadata/domaincaps-full.xml b/tests/domaincapsschemadata/domaincaps-full.xml index 96202bc..d4f91fa 100644 --- a/tests/domaincapsschemadata/domaincaps-full.xml +++ b/tests/domaincapsschemadata/domaincaps-full.xml @@ -68,4 +68,7 @@ </enum> </hostdev> </devices> + <features> + <gic supported='no'/> + </features> </domainCapabilities> diff --git a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml index 37d2102..990661b 100644 --- a/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml +++ b/tests/domaincapsschemadata/domaincaps-qemu_1.6.50-1.xml @@ -56,4 +56,7 @@ </enum> </hostdev> </devices> + <features> + <gic supported='no'/> + </features> </domainCapabilities> -- 2.5.5

On 04/18/2016 01:44 PM, Andrea Bolognani wrote:
Add information about GIC capabilities to virDomainCaps and update the formatter to include them in the XML output. --- src/conf/domain_capabilities.c | 36 ++++++++++++++++++++++ src/conf/domain_capabilities.h | 10 ++++++ tests/domaincapsschemadata/domaincaps-basic.xml | 3 ++ tests/domaincapsschemadata/domaincaps-full.xml | 3 ++ .../domaincaps-qemu_1.6.50-1.xml | 3 ++ 5 files changed, 55 insertions(+)
ACK - Cole

Take the GIC capabilities stored in a virQEMUCaps instance and update a virDomainCaps instance appropriately. --- src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 4afc6b6..ee80be2 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -4082,6 +4082,60 @@ virQEMUCapsFillDomainDeviceHostdevCaps(virQEMUCapsPtr qemuCaps, } +/** + * virQEMUCapsFillDomainFeatureGICCaps: + * @qemuCaps: QEMU capabilities + * @domCaps: domain capabilities + * + * Take the information about GIC capabilities that has been obtained + * using the 'query-gic-capabilities' QMP command and stored in @qemuCaps + * and convert it to a form suitable for @domCaps. + * + * @qemuCaps contains complete information about the GIC capabilities for + * the corresponding QEMU binary, stored as custom objects; @domCaps, on + * the other hand, should only contain information about the GIC versions + * available for the specific combination of architecture, machine type + * and virtualization type. Moreover, a common format is used to store + * information about enumerations in @domCaps, so further processing is + * required. + * + * Returns: 0 on success, <0 on failure + */ +static int +virQEMUCapsFillDomainFeatureGICCaps(virQEMUCapsPtr qemuCaps, + virDomainCapsPtr domCaps) +{ + virDomainCapsFeatureGICPtr gic = &domCaps->gic; + size_t i; + + if (domCaps->arch != VIR_ARCH_ARMV7L && + domCaps->arch != VIR_ARCH_AARCH64) + return 0; + + if (STRNEQ(domCaps->machine, "virt") && + !STRPREFIX(domCaps->machine, "virt-")) + return 0; + + for (i = 0; i < qemuCaps->ngicCapabilities; i++) { + virGICCapabilityPtr cap = &qemuCaps->gicCapabilities[i]; + + if (domCaps->virttype == VIR_DOMAIN_VIRT_KVM && + !(cap->implementation & VIR_GIC_IMPLEMENTATION_KERNEL)) + continue; + + if (domCaps->virttype == VIR_DOMAIN_VIRT_QEMU && + !(cap->implementation & VIR_GIC_IMPLEMENTATION_EMULATED)) + continue; + + gic->supported = true; + VIR_DOMAIN_CAPS_ENUM_SET(gic->version, + cap->version); + } + + return 0; +} + + int virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, virQEMUCapsPtr qemuCaps, @@ -4098,7 +4152,8 @@ virQEMUCapsFillDomainCaps(virDomainCapsPtr domCaps, if (virQEMUCapsFillDomainOSCaps(qemuCaps, os, loader, nloader) < 0 || virQEMUCapsFillDomainDeviceDiskCaps(qemuCaps, domCaps->machine, disk) < 0 || - virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0) + virQEMUCapsFillDomainDeviceHostdevCaps(qemuCaps, hostdev) < 0 || + virQEMUCapsFillDomainFeatureGICCaps(qemuCaps, domCaps) < 0) return -1; return 0; } -- 2.5.5

On 04/18/2016 01:44 PM, Andrea Bolognani wrote:
Take the GIC capabilities stored in a virQEMUCaps instance and update a virDomainCaps instance appropriately. --- src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-)
ACK - Cole

Implement support for saving GIC capabilities in the cache and read them back. --- src/qemu/qemu_capabilities.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index ee80be2..be3e420 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2926,6 +2926,77 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename, } VIR_FREE(nodes); + if ((n = virXPathNodeSet("./gic", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu capabilities gic")); + goto cleanup; + } + if (n > 0) { + unsigned int uintValue; + bool boolValue; + + qemuCaps->ngicCapabilities = n; + if (VIR_ALLOC_N(qemuCaps->gicCapabilities, n) < 0) + goto cleanup; + + for (i = 0; i < n; i++) { + virGICCapabilityPtr cap = &qemuCaps->gicCapabilities[i]; + + if (!(str = virXMLPropString(nodes[i], "version"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing GIC version " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + virStrToLong_ui(str, NULL, 10, &uintValue) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed GIC version " + "in QEMU capabilities cache")); + goto cleanup; + } + cap->version = uintValue; + VIR_FREE(str); + + if (!(str = virXMLPropString(nodes[i], "kernel"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing in-kernel GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + !(boolValue = STREQ(str, "true")) && + STRNEQ(str, "false")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed in-kernel GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (boolValue) + cap->implementation |= VIR_GIC_IMPLEMENTATION_KERNEL; + VIR_FREE(str); + + if (!(str = virXMLPropString(nodes[i], "emulated"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing emulated GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + !(boolValue = STREQ(str, "true")) && + STRNEQ(str, "false")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed emulated GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (boolValue) + cap->implementation |= VIR_GIC_IMPLEMENTATION_EMULATED; + VIR_FREE(str); + } + } + VIR_FREE(nodes); + ret = 0; cleanup: VIR_FREE(str); @@ -2992,6 +3063,22 @@ virQEMUCapsSaveCache(virQEMUCapsPtr qemuCaps, const char *filename) qemuCaps->machineMaxCpus[i]); } + for (i = 0; i < qemuCaps->ngicCapabilities; i++) { + virGICCapabilityPtr cap; + bool kernel; + bool emulated; + + cap = &qemuCaps->gicCapabilities[i]; + kernel = (cap->implementation & VIR_GIC_IMPLEMENTATION_KERNEL); + emulated = (cap->implementation & VIR_GIC_IMPLEMENTATION_EMULATED); + + virBufferAsprintf(&buf, + "<gic version='%d' kernel='%s' emulated='%s'/>\n", + cap->version, + kernel ? "true" : "false", + emulated ? "true" : "false"); + } + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</qemuCaps>\n"); -- 2.5.5

On 04/18/2016 01:44 PM, Andrea Bolognani wrote:
Implement support for saving GIC capabilities in the cache and read them back. --- src/qemu/qemu_capabilities.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+)
I was surprised by lack of test cases, but it seems a common problem in this area of the code, so nothing to handle for this patch series... One comment below
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index ee80be2..be3e420 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2926,6 +2926,77 @@ virQEMUCapsLoadCache(virQEMUCapsPtr qemuCaps, const char *filename, } VIR_FREE(nodes);
+ if ((n = virXPathNodeSet("./gic", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu capabilities gic")); + goto cleanup; + } + if (n > 0) { + unsigned int uintValue; + bool boolValue; + + qemuCaps->ngicCapabilities = n; + if (VIR_ALLOC_N(qemuCaps->gicCapabilities, n) < 0) + goto cleanup; + + for (i = 0; i < n; i++) { + virGICCapabilityPtr cap = &qemuCaps->gicCapabilities[i]; + + if (!(str = virXMLPropString(nodes[i], "version"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing GIC version " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + virStrToLong_ui(str, NULL, 10, &uintValue) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed GIC version " + "in QEMU capabilities cache")); + goto cleanup; + } + cap->version = uintValue; + VIR_FREE(str); + + if (!(str = virXMLPropString(nodes[i], "kernel"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing in-kernel GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + !(boolValue = STREQ(str, "true")) && + STRNEQ(str, "false")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed in-kernel GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (boolValue) + cap->implementation |= VIR_GIC_IMPLEMENTATION_KERNEL; + VIR_FREE(str); + + if (!(str = virXMLPropString(nodes[i], "emulated"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing emulated GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (str && + !(boolValue = STREQ(str, "true")) && + STRNEQ(str, "false")) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed emulated GIC information " + "in QEMU capabilities cache")); + goto cleanup; + } + if (boolValue) + cap->implementation |= VIR_GIC_IMPLEMENTATION_EMULATED; + VIR_FREE(str); + } + } + VIR_FREE(nodes); + ret = 0; cleanup: VIR_FREE(str); @@ -2992,6 +3063,22 @@ virQEMUCapsSaveCache(virQEMUCapsPtr qemuCaps, const char *filename) qemuCaps->machineMaxCpus[i]); }
+ for (i = 0; i < qemuCaps->ngicCapabilities; i++) { + virGICCapabilityPtr cap; + bool kernel; + bool emulated; + + cap = &qemuCaps->gicCapabilities[i]; + kernel = (cap->implementation & VIR_GIC_IMPLEMENTATION_KERNEL); + emulated = (cap->implementation & VIR_GIC_IMPLEMENTATION_EMULATED); + + virBufferAsprintf(&buf, + "<gic version='%d' kernel='%s' emulated='%s'/>\n", + cap->version, + kernel ? "true" : "false", + emulated ? "true" : "false"); + } + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</qemuCaps>\n");
Use of literal 'true'/'false' isn't common in our XML formats. This isn't user facing, but still probably better to use 'yes'/'no', if only so that some future cleanup can streamline things here :) ACK otherwise - Cole

On Tue, 2016-04-19 at 18:52 -0400, Cole Robinson wrote:
On 04/18/2016 01:44 PM, Andrea Bolognani wrote:
Implement support for saving GIC capabilities in the cache and read them back. --- src/qemu/qemu_capabilities.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) I was surprised by lack of test cases, but it seems a common problem in this area of the code, so nothing to handle for this patch series...
Yeah, I mentioned that in the cover letter... There's some stuff in tests/domaincapstest.c but it's far from having good coverage - AFAICT it only tests formatting the capabilities, not parsing them.
+ for (i = 0; i < qemuCaps->ngicCapabilities; i++) { + virGICCapabilityPtr cap; + bool kernel; + bool emulated; + + cap = &qemuCaps->gicCapabilities[i]; + kernel = (cap->implementation & VIR_GIC_IMPLEMENTATION_KERNEL); + emulated = (cap->implementation & VIR_GIC_IMPLEMENTATION_EMULATED); + + virBufferAsprintf(&buf, + "<gic version='%d' kernel='%s' emulated='%s'/>\n", + cap->version, + kernel ? "true" : "false", + emulated ? "true" : "false"); + } + virBufferAdjustIndent(&buf, -2); virBufferAddLit(&buf, "</qemuCaps>\n"); Use of literal 'true'/'false' isn't common in our XML formats. This isn't user facing, but still probably better to use 'yes'/'no', if only so that some future cleanup can streamline things here :)
I've changed it to yes/no and pushed the whole series. Thanks for your review! :) -- Andrea Bolognani Software Engineer - Virtualization Team

--- docs/formatdomain.html.in | 3 ++- docs/formatdomaincaps.html.in | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 9bcef6a..54ad99b 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1497,7 +1497,8 @@ All features are listed within the <code>features</code> element, omitting a togglable feature tag turns it off. The available features can be found by asking - for the <a href="formatcaps.html">capabilities XML</a>, + for the <a href="formatcaps.html">capabilities XML</a> and + <a href="formatdomaincaps.html">domain capabilities XML</a>, but a common set for fully virtualized domains are: </p> diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index 850109f..0c40321 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -145,7 +145,7 @@ <h3><a name="elementsDevices">Devices</a></h3> <p> - The final set of XML elements describe the supported devices and their + Another set of XML elements describe the supported devices and their capabilities. All devices occur as children of the main <code>devices</code> element. </p> @@ -277,5 +277,46 @@ <dd>Options for the <code>name</code> attribute of the <driver/> element.</dd> </dl> + + <h3><a name="elementsFeatures">Features</a></h3> + + <p>One more set of XML elements describe the supported features and + their capabilities. All features occur as children of the main + <code>features</code> element.</p> + +<pre> +<domainCapabilities> + ... + <features> + <gic supported='yes'> + <enum name='version'> + <value>2</value> + <value>3</value> + </enum> + </gic> + </features> +</domainCapabilities> +</pre> + + <p>Reported capabilities are expressed as an enumerated list of + possible values for each of the elements or attributes. For example, the + <code>gic</code> element has an attribute <code>version</code> which can + support the values <code>2</code> or <code>3</code>.</p> + + <p>For information about the purpose of each feature, see the + <a href="formatdomain.html#elementsFeatures">relevant section</a> in + the domain XML documentation. + </p> + + <h4><a name="elementsGIC">GIC capabilities</a></h4> + + <p>GIC capabilities are exposed under the <code>gic</code> element.</p> + + <dl> + <dt>version</dt> + <dd>Options for the <code>version</code> attribute of the + <code>gic</code> element.</dd> + </dl> + </body> </html> -- 2.5.5

On 04/18/2016 01:44 PM, Andrea Bolognani wrote:
--- docs/formatdomain.html.in | 3 ++- docs/formatdomaincaps.html.in | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-)
ACK - Cole

On Mon, 2016-04-18 at 19:43 +0200, Andrea Bolognani wrote:
Changes from [RFC]: * Fix issues pointed out during review (see patches 1 and 2 for details) * Add documentation The only thing missing AFAIK is some test cases... I'm not sure whether it's possible to include QMP replies for QEMU 2.6 even though it hasn't been released yet, and I wouldn't know how to generate a .replies file anyway. Any pointers?
Things I forgot to mention yesterday: * John suggested squashing some patches together, but I haven't done so because my understanding is that it would just have made review easier, and I think at this point deviating from the RFC would actually have the opposite effect. I'm not against doing so, though * It was also questioned whether patch 6, which deals with saving and restoring the QEMU capabilities, should appear earlier in the series. I don't expect a feature to work properly until the whole series has been applied, so I don't think it's worth shuffling patches around just because of that, but I could be convinced otherwise Cheers. -- Andrea Bolognani Software Engineer - Virtualization Team
participants (2)
-
Andrea Bolognani
-
Cole Robinson