diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8c884f4af9cb4bd8ef47c6be42d8d13d5ed38fe9..bfc1df390927687ddc3cb8966e2a7fd6bd3cc69b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1678,6 +1678,7 @@
</kvm>
<pvspinlock state='on'/>
<gic version='2'/>
+ <ioapic driver='qemu'/>
</features>
...
@@ -1839,6 +1840,14 @@
for hypervisor to decide.
Since 2.1.0
+
ioapic
+ Tune the I/O APIC. Possible values for the
+ driver
attribute are:
+ kvm
(default for KVM domains)
+ and qemu
which puts I/O APIC in userspace
+ which is also known as a split I/O APIC mode.
+ Since 3.4.0 (QEMU/KVM only)
+
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 281309ec09dae1652212ea8aa5d36892d355c4a6..64f718b70d12ab75af2f96348f1e172821f768af 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4569,6 +4569,9 @@
+
+
+
@@ -4747,6 +4750,18 @@
+
+
+
+
+ qemu
+ kvm
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0ff216e3a37322adebe0556641b79e7b7715ac82..29b04d3622bc5eb521c2e1fa117ccd6f36c32024 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -141,7 +141,8 @@ VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"pmu",
"vmport",
"gic",
- "smm")
+ "smm",
+ "ioapic")
VIR_ENUM_IMPL(virDomainCapabilitiesPolicy, VIR_DOMAIN_CAPABILITIES_POLICY_LAST,
"default",
@@ -859,6 +860,11 @@ VIR_ENUM_IMPL(virDomainLoader,
"rom",
"pflash")
+VIR_ENUM_IMPL(virDomainIOAPIC,
+ VIR_DOMAIN_IOAPIC_LAST,
+ "qemu",
+ "kvm")
+
/* Internal mapping: subset of block job types that can be present in
* XML (remaining types are not two-phase). */
VIR_ENUM_DECL(virDomainBlockJob)
@@ -17527,6 +17533,24 @@ virDomainDefParseXML(xmlDocPtr xml,
ctxt->node = node;
break;
+ case VIR_DOMAIN_FEATURE_IOAPIC:
+ node = ctxt->node;
+ ctxt->node = nodes[i];
+ tmp = virXPathString("string(./@driver)", ctxt);
+ if (tmp) {
+ int value = virDomainIOAPICTypeFromString(tmp);
+ if (value < 0) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("Unknown driver mode: %s"),
+ tmp);
+ goto error;
+ }
+ def->ioapic = value;
+ def->features[val] = VIR_TRISTATE_SWITCH_ON;
+ }
+ ctxt->node = node;
+ break;
+
/* coverity[dead_error_begin] */
case VIR_DOMAIN_FEATURE_LAST:
break;
@@ -24627,6 +24651,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
}
break;
+ case VIR_DOMAIN_FEATURE_IOAPIC:
+ if (def->features[i] == VIR_TRISTATE_SWITCH_ON) {
+ virBufferAsprintf(buf, " \n",
+ virDomainIOAPICTypeToString(def->ioapic));
+ }
+ break;
+
/* coverity[dead_error_begin] */
case VIR_DOMAIN_FEATURE_LAST:
break;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 09fb7aada4b2dade033830452d63a95d10f3e403..82b4785a62f2f211930cb7918d56d8ce8d66f896 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1670,6 +1670,7 @@ typedef enum {
VIR_DOMAIN_FEATURE_VMPORT,
VIR_DOMAIN_FEATURE_GIC,
VIR_DOMAIN_FEATURE_SMM,
+ VIR_DOMAIN_FEATURE_IOAPIC,
VIR_DOMAIN_FEATURE_LAST
} virDomainFeature;
@@ -1809,6 +1810,15 @@ struct _virDomainLoaderDef {
void virDomainLoaderDefFree(virDomainLoaderDefPtr loader);
+typedef enum {
+ VIR_DOMAIN_IOAPIC_QEMU = 0,
+ VIR_DOMAIN_IOAPIC_KVM,
+
+ VIR_DOMAIN_IOAPIC_LAST
+} virDomainIOAPIC;
+
+VIR_ENUM_DECL(virDomainIOAPIC);
+
/* Operating system configuration data & machine / arch */
typedef struct _virDomainOSDef virDomainOSDef;
typedef virDomainOSDef *virDomainOSDefPtr;
@@ -2258,6 +2268,7 @@ struct _virDomainDef {
unsigned int hyperv_spinlocks;
virGICVersion gic_version;
char *hyperv_vendor_id;
+ virDomainIOAPIC ioapic;
/* These options are of type virTristateSwitch: ON = keep, OFF = drop */
int caps_features[VIR_DOMAIN_CAPS_FEATURE_LAST];
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu-ioapic.xml b/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu-ioapic.xml
new file mode 100644
index 0000000000000000000000000000000000000000..284d63a300751035fb419ea2103ff7f570386432
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-intel-iommu-ioapic.xml
@@ -0,0 +1,29 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-x86_64
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu-ioapic.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu-ioapic.xml
new file mode 120000
index 0000000000000000000000000000000000000000..42d17b2c05c4e86e6e3d94b4fce378163dcaeebd
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-intel-iommu-ioapic.xml
@@ -0,0 +1 @@
+../qemuxml2argvdata/qemuxml2argv-intel-iommu-ioapic.xml
\ No newline at end of file
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 2dccde746ef186e1ff2d7be1787ebc5939e4bb7c..0f00b20d39a3871e3c2e3211638d76fcf9b4b3ce 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1122,6 +1122,7 @@ mymain(void)
DO_TEST("intel-iommu-machine",
QEMU_CAPS_MACHINE_OPT,
QEMU_CAPS_MACHINE_IOMMU);
+ DO_TEST("intel-iommu-ioapic", NONE);
DO_TEST("cpu-check-none", NONE);
DO_TEST("cpu-check-partial", NONE);