intel_iommu: pass whole remapped addresses to apic

The MMIO interface to APIC only allowed 8 bit addresses, which is not
enough for 32 bit addresses from EIM remapping.
Intel stored upper 24 bits in the high MSI address, so use the same
technique. The technique is also used in KVM MSI interface.
Other APICs are unlikely to handle those upper bits.

Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
Radim Krčmář 2016-10-10 17:28:44 +02:00 committed by Eduardo Habkost
parent 267ee35715
commit 329460191d

View File

@ -32,6 +32,7 @@
#include "hw/i386/x86-iommu.h" #include "hw/i386/x86-iommu.h"
#include "hw/pci-host/q35.h" #include "hw/pci-host/q35.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "hw/i386/apic_internal.h"
/*#define DEBUG_INTEL_IOMMU*/ /*#define DEBUG_INTEL_IOMMU*/
#ifdef DEBUG_INTEL_IOMMU #ifdef DEBUG_INTEL_IOMMU
@ -280,18 +281,17 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg, static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg,
hwaddr mesg_data_reg) hwaddr mesg_data_reg)
{ {
hwaddr addr; MSIMessage msi;
uint32_t data;
assert(mesg_data_reg < DMAR_REG_SIZE); assert(mesg_data_reg < DMAR_REG_SIZE);
assert(mesg_addr_reg < DMAR_REG_SIZE); assert(mesg_addr_reg < DMAR_REG_SIZE);
addr = vtd_get_long_raw(s, mesg_addr_reg); msi.address = vtd_get_long_raw(s, mesg_addr_reg);
data = vtd_get_long_raw(s, mesg_data_reg); msi.data = vtd_get_long_raw(s, mesg_data_reg);
VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data); VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32,
address_space_stl_le(&address_space_memory, addr, data, msi.address, msi.data);
MEMTXATTRS_UNSPECIFIED, NULL); apic_get_class()->send_msi(&msi);
} }
/* Generate a fault event to software via MSI if conditions are met. /* Generate a fault event to software via MSI if conditions are met.
@ -2134,6 +2134,7 @@ static void vtd_generate_msi_message(VTDIrq *irq, MSIMessage *msg_out)
msg.dest_mode = irq->dest_mode; msg.dest_mode = irq->dest_mode;
msg.redir_hint = irq->redir_hint; msg.redir_hint = irq->redir_hint;
msg.dest = irq->dest; msg.dest = irq->dest;
msg.__addr_hi = irq->dest & 0xffffff00;
msg.__addr_head = cpu_to_le32(0xfee); msg.__addr_head = cpu_to_le32(0xfee);
/* Keep this from original MSI address bits */ /* Keep this from original MSI address bits */
msg.__not_used = irq->msi_addr_last_bits; msg.__not_used = irq->msi_addr_last_bits;
@ -2293,11 +2294,7 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
" for device sid 0x%04x", " for device sid 0x%04x",
to.address, to.data, sid); to.address, to.data, sid);
if (dma_memory_write(&address_space_memory, to.address, apic_get_class()->send_msi(&to);
&to.data, size)) {
VTD_DPRINTF(GENERAL, "error: fail to write 0x%"PRIx64
" value 0x%"PRIx32, to.address, to.data);
}
return MEMTX_OK; return MEMTX_OK;
} }