aboutsummaryrefslogtreecommitdiff
path: root/hw/intc/ioapic.c
diff options
context:
space:
mode:
authorPeter Xu <peterx@redhat.com>2016-07-14 13:56:23 +0800
committerMichael S. Tsirkin <mst@redhat.com>2016-07-21 20:43:49 +0300
commitcb135f59b8059c3a372652377ef92fa4a49ad550 (patch)
tree244cb6772ba2773c137cc781d96375083f381d89 /hw/intc/ioapic.c
parent09cd058a2cf77bb7a3b10ff93c1f80ed88bca364 (diff)
q35: ioapic: add support for emulated IOAPIC IR
This patch translates all IOAPIC interrupts into MSI ones. One pseudo ioapic address space is added to transfer the MSI message. By default, it will be system memory address space. When IR is enabled, it will be IOMMU address space. Currently, only emulated IOAPIC is supported. Idea suggested by Jan Kiszka and Rita Sinha in the following patch: https://lists.gnu.org/archive/html/qemu-devel/2016-03/msg01933.html Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/intc/ioapic.c')
-rw-r--r--hw/intc/ioapic.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index 273bb0854c..36dd42af20 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -29,6 +29,8 @@
#include "hw/i386/ioapic_internal.h"
#include "include/hw/pci/msi.h"
#include "sysemu/kvm.h"
+#include "target-i386/cpu.h"
+#include "hw/i386/apic-msidef.h"
//#define DEBUG_IOAPIC
@@ -50,13 +52,15 @@ extern int ioapic_no;
static void ioapic_service(IOAPICCommonState *s)
{
+ AddressSpace *ioapic_as = PC_MACHINE(qdev_get_machine())->ioapic_as;
+ uint32_t addr, data;
uint8_t i;
uint8_t trig_mode;
uint8_t vector;
uint8_t delivery_mode;
uint32_t mask;
uint64_t entry;
- uint8_t dest;
+ uint16_t dest_idx;
uint8_t dest_mode;
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
@@ -67,7 +71,14 @@ static void ioapic_service(IOAPICCommonState *s)
entry = s->ioredtbl[i];
if (!(entry & IOAPIC_LVT_MASKED)) {
trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
- dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+ /*
+ * By default, this would be dest_id[8] +
+ * reserved[8]. When IR is enabled, this would be
+ * interrupt_index[15] + interrupt_format[1]. This
+ * field never means anything, but only used to
+ * generate corresponding MSI.
+ */
+ dest_idx = entry >> IOAPIC_LVT_DEST_IDX_SHIFT;
dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
delivery_mode =
(entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
@@ -97,8 +108,17 @@ static void ioapic_service(IOAPICCommonState *s)
#else
(void)coalesce;
#endif
- apic_deliver_irq(dest, dest_mode, delivery_mode, vector,
- trig_mode);
+ /* No matter whether IR is enabled, we translate
+ * the IOAPIC message into a MSI one, and its
+ * address space will decide whether we need a
+ * translation. */
+ addr = APIC_DEFAULT_ADDRESS | \
+ (dest_idx << MSI_ADDR_DEST_IDX_SHIFT) |
+ (dest_mode << MSI_ADDR_DEST_MODE_SHIFT);
+ data = (vector << MSI_DATA_VECTOR_SHIFT) |
+ (trig_mode << MSI_DATA_TRIGGER_SHIFT) |
+ (delivery_mode << MSI_DATA_DELIVERY_MODE_SHIFT);
+ stl_le_phys(ioapic_as, addr, data);
}
}
}