</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>
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</li>
+ <li>
+ The optional <code>event_idx</code> 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.
+ <span class="since">Since 0.9.5 (QEMU and KVM only)</span>
+ <b>In general you should leave this option alone, unless you
+ are very certain you know what you are doing.</b>
+ </li>
</ul>
</dd>
<dt><code>boot</code></dt>
<source network='default'/>
<target dev='vnet1'/>
<model type='virtio'/>
- <b><driver name='vhost' txmode='iothread' ioeventfd='on'/></b>
+ <b><driver name='vhost' txmode='iothread' ioeventfd='on' event_idx='off'/></b>
</interface>
</devices>
...</pre>
on overloaded host it could increase guest I/O latency.
<span class="since">Since 0.9.3 (QEMU and KVM only)</span><br/><br/>
+ <b>In general you should leave this option alone, unless you
+ are very certain you know what you are doing.</b>
+ </dd>
+ <dt><code>event_idx</code></dt>
+ <dd>
+ The <code>event_idx</code> 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.
+ <span class="since">Since 0.9.5 (QEMU and KVM only)</span><br/><br/>
+
<b>In general you should leave this option alone, unless you
are very certain you know what you are doing.</b>
</dd>
<optional>
<ref name="ioeventfd"/>
</optional>
+ <optional>
+ <ref name="event_idx"/>
+ </optional>
<empty/>
</element>
</define>
</choice>
</attribute>
</define>
+ <define name="event_idx">
+ <attribute name="event_idx">
+ <choice>
+ <value>on</value>
+ <value>off</value>
+ </choice>
+ </attribute>
+ </define>
<define name="controller">
<element name="controller">
<choice>
<optional>
<ref name="ioeventfd"/>
</optional>
+ <optional>
+ <ref name="event_idx"/>
+ </optional>
<empty/>
</element>
</optional>
"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",
char *error_policy = NULL;
char *iotag = NULL;
char *ioeventfd = NULL;
+ char *event_idx = NULL;
char *devaddr = NULL;
virStorageEncryptionPtr encryption = NULL;
char *serial = NULL;
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")) {
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) {
VIR_FREE(error_policy);
VIR_FREE(iotag);
VIR_FREE(ioeventfd);
+ VIR_FREE(event_idx);
VIR_FREE(devaddr);
VIR_FREE(serial);
virStorageEncryptionFree(encryption);
char *backend = NULL;
char *txmode = NULL;
char *ioeventfd = NULL;
+ char *event_idx = NULL;
char *filter = NULL;
char *internal = NULL;
char *devaddr = NULL;
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);
}
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) {
VIR_FREE(backend);
VIR_FREE(txmode);
VIR_FREE(ioeventfd);
+ VIR_FREE(event_idx);
VIR_FREE(filter);
VIR_FREE(type);
VIR_FREE(internal);
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,
type, device);
if (def->driverName || def->driverType || def->cachemode ||
- def->ioeventfd) {
+ def->ioeventfd || def->event_idx) {
virBufferAsprintf(buf, " <driver");
if (def->driverName)
virBufferAsprintf(buf, " name='%s'", def->driverName);
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");
}
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");
}
}
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;
int bootIndex;
int iomode;
int ioeventfd;
+ int event_idx;
unsigned int readonly : 1;
unsigned int shared : 1;
virDomainDeviceInfo info;
enum virDomainNetBackendType name; /* which driver backend to use */
enum virDomainNetVirtioTxModeType txmode;
enum virDomainIoEventFd ioeventfd;
+ enum virDomainVirtioEventIdx event_idx;
} virtio;
} driver;
union {
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)
virDomainVideoDefaultType;
virDomainVideoTypeFromString;
virDomainVideoTypeToString;
+virDomainVirtioEventIdxTypeFromString;
+virDomainVirtioEventIdxTypeToString;
virDomainVirtTypeToString;
virDomainWatchdogActionTypeFromString;
virDomainWatchdogActionTypeToString;
"pci-multifunction", /* 60 */
"virtio-blk-pci.ioeventfd",
"sga",
+ "virtio-blk-pci.event_idx",
+ "virtio-net-pci.event_idx",
);
struct qemu_feature_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;
}
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 */
};
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:
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
--- /dev/null
+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
--- /dev/null
+<domain type='qemu'>
+ <name>test</name>
+ <uuid>bba65c0e-c049-934f-b6aa-4e2c0582acdf</uuid>
+ <memory>1048576</memory>
+ <currentMemory>1048576</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='x86_64' machine='pc-0.13'>hvm</type>
+ <boot dev='cdrom'/>
+ <boot dev='hd'/>
+ <bootmenu enable='yes'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>restart</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2' event_idx='on'/>
+ <source file='/var/lib/libvirt/images/f14.img'/>
+ <target dev='vda' bus='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source file='/var/lib/libvirt/Fedora-14-x86_64-Live-KDE.iso'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='virtio-serial' index='0'>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
+ </controller>
+ <controller type='ide' index='0'/>
+ <interface type='user'>
+ <mac address='52:54:00:e5:48:58'/>
+ <model type='virtio'/>
+ <driver name='vhost' event_idx='off'/>
+ </interface>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target type='serial' port='0'/>
+ </console>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='5091' autoport='no' listen='127.0.0.1'>
+ <listen type='address' address='127.0.0.1'/>
+ </graphics>
+ <video>
+ <model type='vga' vram='9216' heads='1'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
+ </video>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
DO_TEST("disk-ioeventfd", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_VIRTIO_IOEVENTFD,
QEMU_CAPS_VIRTIO_TX_ALG, QEMU_CAPS_DEVICE);
+ DO_TEST("event_idx", false,
+ QEMU_CAPS_DRIVE,
+ QEMU_CAPS_VIRTIO_BLK_EVENT_IDX,
+ QEMU_CAPS_VIRTIO_NET_EVENT_IDX,
+ QEMU_CAPS_DEVICE);
DO_TEST("graphics-vnc", false, NONE);
DO_TEST("graphics-vnc-socket", false, NONE);
DO_TEST("smp");
DO_TEST("lease");
+ DO_TEST("event_idx");
/* These tests generate different XML */
DO_TEST_DIFFERENT("balloon-device-auto");