diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 7d2ba8a09d..f46771df0f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -904,7 +904,7 @@ </disk> ... <disk type='network'> - <driver name="qemu" type="raw" io="threads" ioeventfd="on"/> + <driver name="qemu" type="raw" io="threads" ioeventfd="on" event_idx="off"/> <source protocol="sheepdog" name="image_name"> <host name="hostname" port="7000"/> </source> @@ -1004,6 +1004,19 @@ In general you should leave this option alone, unless you are very certain you know what you are doing. +
  • + The optional event_idx attribute controls + some aspects of device event processing. The value can be + either 'on' or 'off' - if it is on, it will reduce the + number of interupts and exits for the guest. The default + is determined by QEMU; usually if the feature is + supported, default is on. In case there is a situation + where this behavior is suboptimal, this attribute provides + a way to force the feature off. + Since 0.9.5 (QEMU and KVM only) + In general you should leave this option alone, unless you + are very certain you know what you are doing. +
  • boot
    @@ -1850,7 +1863,7 @@ qemu-kvm -net nic,model=? /dev/null <source network='default'/> <target dev='vnet1'/> <model type='virtio'/> - <driver name='vhost' txmode='iothread' ioeventfd='on'/> + <driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off'/> </interface> </devices> ... @@ -1914,6 +1927,20 @@ qemu-kvm -net nic,model=? /dev/null on overloaded host it could increase guest I/O latency. Since 0.9.3 (QEMU and KVM only)

    + In general you should leave this option alone, unless you + are very certain you know what you are doing. + +
    event_idx
    +
    + The event_idx attribute controls some aspects of + device event processing. The value can be either 'on' or 'off' + - if it is on, it will reduce the number of interupts and + exits for the guest. The default is determined by QEMU; + usually if the feature is supported, default is on. In case + there is a situation where this behavior is suboptimal, this + attribute provides a way to force the feature off. + Since 0.9.5 (QEMU and KVM only)

    + In general you should leave this option alone, unless you are very certain you know what you are doing.
    diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 6ccbeed271..dd8c41ae0c 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -807,6 +807,9 @@ + + + @@ -854,6 +857,14 @@ + + + + on + off + + + @@ -1165,6 +1176,9 @@ + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 010ce571c0..ce1f3c552f 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -182,6 +182,10 @@ VIR_ENUM_IMPL(virDomainIoEventFd, VIR_DOMAIN_IO_EVENT_FD_LAST, "on", "off") +VIR_ENUM_IMPL(virDomainVirtioEventIdx, VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST, + "default", + "on", + "off") VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "ide", @@ -2081,6 +2085,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, char *error_policy = NULL; char *iotag = NULL; char *ioeventfd = NULL; + char *event_idx = NULL; char *devaddr = NULL; virStorageEncryptionPtr encryption = NULL; char *serial = NULL; @@ -2197,6 +2202,7 @@ virDomainDiskDefParseXML(virCapsPtr caps, error_policy = virXMLPropString(cur, "error_policy"); iotag = virXMLPropString(cur, "io"); ioeventfd = virXMLPropString(cur, "ioeventfd"); + event_idx = virXMLPropString(cur, "event_idx"); } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { def->readonly = 1; } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { @@ -2351,6 +2357,24 @@ virDomainDiskDefParseXML(virCapsPtr caps, def->ioeventfd=i; } + if (event_idx) { + if (def->bus != VIR_DOMAIN_DISK_BUS_VIRTIO) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("disk event_idx mode supported " + "only for virtio bus")); + goto error; + } + + int idx; + if ((idx = virDomainVirtioEventIdxTypeFromString(event_idx)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown disk event_idx mode '%s'"), + event_idx); + goto error; + } + def->event_idx = idx; + } + if (devaddr) { if (virDomainParseLegacyDeviceAddress(devaddr, &def->info.addr.pci) < 0) { @@ -2414,6 +2438,7 @@ cleanup: VIR_FREE(error_policy); VIR_FREE(iotag); VIR_FREE(ioeventfd); + VIR_FREE(event_idx); VIR_FREE(devaddr); VIR_FREE(serial); virStorageEncryptionFree(encryption); @@ -2744,6 +2769,7 @@ virDomainNetDefParseXML(virCapsPtr caps, char *backend = NULL; char *txmode = NULL; char *ioeventfd = NULL; + char *event_idx = NULL; char *filter = NULL; char *internal = NULL; char *devaddr = NULL; @@ -2835,6 +2861,7 @@ virDomainNetDefParseXML(virCapsPtr caps, backend = virXMLPropString(cur, "name"); txmode = virXMLPropString(cur, "txmode"); ioeventfd = virXMLPropString(cur, "ioeventfd"); + event_idx = virXMLPropString(cur, "event_idx"); } else if (xmlStrEqual (cur->name, BAD_CAST "filterref")) { filter = virXMLPropString(cur, "filter"); VIR_FREE(filterparams); @@ -3075,6 +3102,16 @@ virDomainNetDefParseXML(virCapsPtr caps, } def->driver.virtio.ioeventfd = i; } + if (event_idx) { + int idx; + if ((idx = virDomainVirtioEventIdxTypeFromString(event_idx)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown interface event_idx mode '%s'"), + event_idx); + goto error; + } + def->driver.virtio.event_idx = idx; + } } if (filter != NULL) { @@ -3118,6 +3155,7 @@ cleanup: VIR_FREE(backend); VIR_FREE(txmode); VIR_FREE(ioeventfd); + VIR_FREE(event_idx); VIR_FREE(filter); VIR_FREE(type); VIR_FREE(internal); @@ -8576,6 +8614,7 @@ virDomainDiskDefFormat(virBufferPtr buf, const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy); const char *iomode = virDomainDiskIoTypeToString(def->iomode); const char *ioeventfd = virDomainIoEventFdTypeToString(def->ioeventfd); + const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx); if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -8608,7 +8647,7 @@ virDomainDiskDefFormat(virBufferPtr buf, type, device); if (def->driverName || def->driverType || def->cachemode || - def->ioeventfd) { + def->ioeventfd || def->event_idx) { virBufferAsprintf(buf, " driverName) virBufferAsprintf(buf, " name='%s'", def->driverName); @@ -8622,6 +8661,8 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " io='%s'", iomode); if (def->ioeventfd) virBufferAsprintf(buf, " ioeventfd='%s'", ioeventfd); + if (def->event_idx) + virBufferAsprintf(buf, " event_idx='%s'", event_idx); virBufferAsprintf(buf, "/>\n"); } @@ -8996,6 +9037,10 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " ioeventfd='%s'", virDomainIoEventFdTypeToString(def->driver.virtio.ioeventfd)); } + if (def->driver.virtio.event_idx) { + virBufferAsprintf(buf, " event_idx='%s'", + virDomainVirtioEventIdxTypeToString(def->driver.virtio.event_idx)); + } virBufferAddLit(buf, "/>\n"); } } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 1d5af95b41..2cc9b0653f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -209,6 +209,14 @@ enum virDomainIoEventFd { VIR_DOMAIN_IO_EVENT_FD_LAST }; +enum virDomainVirtioEventIdx { + VIR_DOMAIN_VIRTIO_EVENT_IDX_DEFAULT = 0, + VIR_DOMAIN_VIRTIO_EVENT_IDX_ON, + VIR_DOMAIN_VIRTIO_EVENT_IDX_OFF, + + VIR_DOMAIN_VIRTIO_EVENT_IDX_LAST +}; + /* Stores the virtual disk configuration */ typedef struct _virDomainDiskDef virDomainDiskDef; typedef virDomainDiskDef *virDomainDiskDefPtr; @@ -229,6 +237,7 @@ struct _virDomainDiskDef { int bootIndex; int iomode; int ioeventfd; + int event_idx; unsigned int readonly : 1; unsigned int shared : 1; virDomainDeviceInfo info; @@ -377,6 +386,7 @@ struct _virDomainNetDef { enum virDomainNetBackendType name; /* which driver backend to use */ enum virDomainNetVirtioTxModeType txmode; enum virDomainIoEventFd ioeventfd; + enum virDomainVirtioEventIdx event_idx; } virtio; } driver; union { @@ -1661,6 +1671,7 @@ VIR_ENUM_DECL(virDomainDiskErrorPolicy) VIR_ENUM_DECL(virDomainDiskProtocol) VIR_ENUM_DECL(virDomainDiskIo) VIR_ENUM_DECL(virDomainIoEventFd) +VIR_ENUM_DECL(virDomainVirtioEventIdx) VIR_ENUM_DECL(virDomainController) VIR_ENUM_DECL(virDomainControllerModel) VIR_ENUM_DECL(virDomainFS) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 64b91eea3b..4286fbdf16 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -414,6 +414,8 @@ virDomainVideoDefaultRAM; virDomainVideoDefaultType; virDomainVideoTypeFromString; virDomainVideoTypeToString; +virDomainVirtioEventIdxTypeFromString; +virDomainVirtioEventIdxTypeToString; virDomainVirtTypeToString; virDomainWatchdogActionTypeFromString; virDomainWatchdogActionTypeToString; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 3f36212597..f665de4c09 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -123,6 +123,8 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "pci-multifunction", /* 60 */ "virtio-blk-pci.ioeventfd", "sga", + "virtio-blk-pci.event_idx", + "virtio-net-pci.event_idx", ); struct qemu_feature_flags { @@ -1215,6 +1217,10 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags) qemuCapsSet(flags, QEMU_CAPS_VIRTIO_IOEVENTFD); if (strstr(str, "name \"sga\"")) qemuCapsSet(flags, QEMU_CAPS_SGA); + if (strstr(str, "virtio-blk-pci.event_idx")) + qemuCapsSet(flags, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX); + if (strstr(str, "virtio-net-pci.event_idx")) + qemuCapsSet(flags, QEMU_CAPS_VIRTIO_NET_EVENT_IDX); return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index d251262362..13af0b9d7b 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -98,6 +98,8 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_MULTIFUNCTION = 60, /* -device multifunction=on|off */ QEMU_CAPS_VIRTIO_IOEVENTFD = 61, /* IOeventFD feature: virtio-{net|blk}-pci.ioeventfd=on/off */ QEMU_CAPS_SGA = 62, /* Serial Graphics Adapter */ + QEMU_CAPS_VIRTIO_BLK_EVENT_IDX = 63, /* virtio-blk-pci.event_idx */ + QEMU_CAPS_VIRTIO_NET_EVENT_IDX = 64, /* virtio-net-pci.event_idx */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2a4882691c..dbfc7d973c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1585,6 +1585,11 @@ qemuBuildDriveDevStr(virDomainDiskDefPtr disk, case VIR_DOMAIN_DISK_BUS_VIRTIO: virBufferAddLit(&opt, "virtio-blk-pci"); qemuBuildIoEventFdStr(&opt, disk->ioeventfd, qemuCaps); + if (disk->event_idx && + qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_BLK_EVENT_IDX)) { + virBufferAsprintf(&opt, ",event_idx=%s", + virDomainVirtioEventIdxTypeToString(disk->event_idx)); + } qemuBuildDeviceAddressStr(&opt, &disk->info, qemuCaps); break; case VIR_DOMAIN_DISK_BUS_USB: @@ -1808,8 +1813,14 @@ qemuBuildNicDevStr(virDomainNetDefPtr net, goto error; } } - if (usingVirtio) + if (usingVirtio) { qemuBuildIoEventFdStr(&buf, net->driver.virtio.ioeventfd, qemuCaps); + if (net->driver.virtio.event_idx && + qemuCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_EVENT_IDX)) { + virBufferAsprintf(&buf, ",event_idx=%s", + virDomainVirtioEventIdxTypeToString(net->driver.virtio.event_idx)); + } + } if (vlan == -1) virBufferAsprintf(&buf, ",netdev=host%s", net->info.alias); else diff --git a/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args new file mode 100644 index 0000000000..f6ebb60da0 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.args @@ -0,0 +1,11 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu -S -M pc-0.13 -m 1024 -smp 1 -nodefaults \ +-monitor unix:/tmp/test-monitor,server,nowait -no-acpi \ +-boot dc -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 \ +-drive file=/var/lib/libvirt/images/f14.img,if=none,id=drive-virtio-disk0 \ +-device virtio-blk-pci,event_idx=on,bus=pci.0,addr=0x4,drive=drive-virtio-disk0,id=virtio-disk0 \ +-drive file=/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso,if=none,media=cdrom,id=drive-ide0-1-0 \ +-device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 \ +-device virtio-net-pci,event_idx=off,vlan=0,id=net0,mac=52:54:00:e5:48:58,bus=pci.0,addr=0x3 \ +-net user,vlan=0,name=hostnet0 -serial pty -usb -vnc 127.0.0.1:-809 -std-vga \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml new file mode 100644 index 0000000000..81f2200299 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-event_idx.xml @@ -0,0 +1,57 @@ + + test + bba65c0e-c049-934f-b6aa-4e2c0582acdf + 1048576 + 1048576 + 1 + + hvm + + + + + + destroy + restart + restart + + /usr/bin/qemu + + + + +
    + + + + + + +
    + + +
    + + + + + + + + + + + + + + + + + +