aboutsummaryrefslogtreecommitdiff
path: root/hw/i386/x86-iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i386/x86-iommu.c')
-rw-r--r--hw/i386/x86-iommu.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c
index 8a01a2dd25..abc3c03158 100644
--- a/hw/i386/x86-iommu.c
+++ b/hw/i386/x86-iommu.c
@@ -25,6 +25,7 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "trace.h"
+#include "sysemu/kvm.h"
void x86_iommu_iec_register_notifier(X86IOMMUState *iommu,
iec_notify_fn fn, void *data)
@@ -52,6 +53,30 @@ void x86_iommu_iec_notify_all(X86IOMMUState *iommu, bool global,
}
}
+/* Generate one MSI message from VTDIrq info */
+void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *msg_out)
+{
+ X86IOMMU_MSIMessage msg = {};
+
+ /* Generate address bits */
+ msg.dest_mode = irq->dest_mode;
+ msg.redir_hint = irq->redir_hint;
+ msg.dest = irq->dest;
+ msg.__addr_hi = irq->dest & 0xffffff00;
+ msg.__addr_head = cpu_to_le32(0xfee);
+ /* Keep this from original MSI address bits */
+ msg.__not_used = irq->msi_addr_last_bits;
+
+ /* Generate data bits */
+ msg.vector = irq->vector;
+ msg.delivery_mode = irq->delivery_mode;
+ msg.level = 1;
+ msg.trigger_mode = irq->trigger_mode;
+
+ msg_out->address = msg.msi_addr;
+ msg_out->data = msg.msi_data;
+}
+
/* Default X86 IOMMU device */
static X86IOMMUState *x86_iommu_default = NULL;
@@ -94,6 +119,14 @@ static void x86_iommu_realize(DeviceState *dev, Error **errp)
return;
}
+ /* Both Intel and AMD IOMMU IR only support "kernel-irqchip={off|split}" */
+ if (x86_iommu->intr_supported && kvm_irqchip_in_kernel() &&
+ !kvm_irqchip_is_split()) {
+ error_setg(errp, "Interrupt Remapping cannot work with "
+ "kernel-irqchip=on, please use 'split|off'.");
+ return;
+ }
+
if (x86_class->realize) {
x86_class->realize(dev, errp);
}