@@ -24,6 +24,7 @@
#include "exec/address-spaces.h"
#include "intel_iommu_internal.h"
#include "hw/pci/pci.h"
+#include "hw/i386/pc.h"
/*#define DEBUG_INTEL_IOMMU*/
#ifdef DEBUG_INTEL_IOMMU
@@ -266,6 +267,11 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id,
g_hash_table_replace(s->iotlb, key, entry);
}
+static AddressSpace *get_dma_address_space(void)
+{
+ return &PC_MACHINE(qdev_get_machine())->dma_address_space;
+}
+
/* Given the reg addr of both the message data and address, generate an
* interrupt via MSI.
*/
@@ -282,7 +288,7 @@ static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg,
data = vtd_get_long_raw(s, mesg_data_reg);
VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data);
- address_space_stl_le(&address_space_memory, addr, data,
+ address_space_stl_le(get_dma_address_space(), addr, data,
MEMTXATTRS_UNSPECIFIED, NULL);
}
@@ -496,7 +502,7 @@ static int vtd_get_root_entry(IntelIOMMUState *s, uint8_t index,
dma_addr_t addr;
addr = s->root + index * sizeof(*re);
- if (dma_memory_read(&address_space_memory, addr, re, sizeof(*re))) {
+ if (dma_memory_read(get_dma_address_space(), addr, re, sizeof(*re))) {
VTD_DPRINTF(GENERAL, "error: fail to access root-entry at 0x%"PRIx64
" + %"PRIu8, s->root, index);
re->val = 0;
@@ -521,7 +527,7 @@ static int vtd_get_context_entry_from_root(VTDRootEntry *root, uint8_t index,
return -VTD_FR_ROOT_ENTRY_P;
}
addr = (root->val & VTD_ROOT_ENTRY_CTP) + index * sizeof(*ce);
- if (dma_memory_read(&address_space_memory, addr, ce, sizeof(*ce))) {
+ if (dma_memory_read(get_dma_address_space(), addr, ce, sizeof(*ce))) {
VTD_DPRINTF(GENERAL, "error: fail to access context-entry at 0x%"PRIx64
" + %"PRIu8,
(uint64_t)(root->val & VTD_ROOT_ENTRY_CTP), index);
@@ -555,7 +561,7 @@ static uint64_t vtd_get_slpte(dma_addr_t base_addr, uint32_t index)
assert(index < VTD_SL_PT_ENTRY_NR);
- if (dma_memory_read(&address_space_memory,
+ if (dma_memory_read(get_dma_address_space(),
base_addr + index * sizeof(slpte), &slpte,
sizeof(slpte))) {
slpte = (uint64_t)-1;
@@ -1227,7 +1233,7 @@ static bool vtd_get_inv_desc(dma_addr_t base_addr, uint32_t offset,
VTDInvDesc *inv_desc)
{
dma_addr_t addr = base_addr + offset * sizeof(*inv_desc);
- if (dma_memory_read(&address_space_memory, addr, inv_desc,
+ if (dma_memory_read(get_dma_address_space(), addr, inv_desc,
sizeof(*inv_desc))) {
VTD_DPRINTF(GENERAL, "error: fail to fetch Invalidation Descriptor "
"base_addr 0x%"PRIx64 " offset %"PRIu32, base_addr, offset);
@@ -1262,8 +1268,8 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
VTD_DPRINTF(INV, "status data 0x%x, status addr 0x%"PRIx64,
status_data, status_addr);
status_data = cpu_to_le32(status_data);
- if (dma_memory_write(&address_space_memory, status_addr, &status_data,
- sizeof(status_data))) {
+ if (dma_memory_write(get_dma_address_space(), status_addr,
+ &status_data, sizeof(status_data))) {
VTD_DPRINTF(GENERAL, "error: fail to perform a coherent write");
return false;
}
@@ -1845,7 +1851,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
IntelIOMMUState *s = vtd_as->iommu_state;
IOMMUTLBEntry ret = {
- .target_as = &address_space_memory,
+ .target_as = get_dma_address_space(),
.iova = addr,
.translated_addr = 0,
.addr_mask = ~(hwaddr)0,
@@ -10,6 +10,7 @@
* See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/apic_internal.h"
#include "hw/pci/msi.h"
#include "sysemu/kvm.h"
@@ -147,14 +148,13 @@ static void kvm_apic_external_nmi(APICCommonState *s)
run_on_cpu(CPU(s->cpu), do_inject_external_nmi, s);
}
-static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr,
- unsigned size)
+static uint64_t kvm_msi_region_read(void *opaque, hwaddr addr, unsigned size)
{
return ~(uint64_t)0;
}
-static void kvm_apic_mem_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
+static void kvm_msi_region_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
{
MSIMessage msg = { .address = addr, .data = data };
int ret;
@@ -166,10 +166,14 @@ static void kvm_apic_mem_write(void *opaque, hwaddr addr,
}
}
-static const MemoryRegionOps kvm_apic_io_ops = {
- .read = kvm_apic_mem_read,
- .write = kvm_apic_mem_write,
+static const MemoryRegionOps kvm_msi_region_ops = {
+ .read = kvm_msi_region_read,
+ .write = kvm_msi_region_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static void kvm_apic_reset(APICCommonState *s)
@@ -182,8 +186,10 @@ static void kvm_apic_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
- memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",
- APIC_SPACE_SIZE);
+ memory_region_init(&s->io_memory, NULL, "kvm-apic", APIC_SPACE_SIZE);
+
+ memory_region_init_io(&s->msi_region, NULL, &kvm_msi_region_ops, NULL,
+ "kvm-msi", MSI_REGION_SIZE);
if (kvm_has_gsi_routing()) {
msi_supported = true;
@@ -26,6 +26,7 @@
#include "hw/i386/pc.h"
#include "hw/char/serial.h"
#include "hw/i386/apic.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/topology.h"
#include "sysemu/cpus.h"
#include "hw/block/fdc.h"
@@ -1281,6 +1282,7 @@ void pc_memory_init(PCMachineState *pcms,
FWCfgState *fw_cfg;
MachineState *machine = MACHINE(pcms);
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+ MemoryRegion *dma, *mem_alias;
assert(machine->ram_size == pcms->below_4g_mem_size +
pcms->above_4g_mem_size);
@@ -1360,6 +1362,21 @@ void pc_memory_init(PCMachineState *pcms,
&pcms->hotplug_memory.mr);
}
+ /* Initialized DMA address space */
+ dma = g_malloc(sizeof(*dma));
+ memory_region_init(dma, NULL, "dma-container",
+ memory_region_size(system_memory));
+ address_space_init(&pcms->dma_address_space, dma, "pc-dma");
+
+ mem_alias = g_malloc(sizeof(*mem_alias));
+ memory_region_init_alias(mem_alias, NULL, "system-memory", system_memory,
+ 0, memory_region_size(system_memory));
+ memory_region_add_subregion_overlap(dma, 0, mem_alias, 0);
+
+ pci_set_dma_address_space(&pcms->dma_address_space);
+ pcms->ioapic_msi_target = &pcms->dma_address_space;
+ pcms->hpet_msi_target = &pcms->dma_address_space;
+
/* Initialize PC system firmware */
pc_system_firmware_init(rom_memory, !pcmc->pci_enabled);
@@ -126,7 +126,6 @@ static void pc_init1(MachineState *machine,
}
pc_cpus_init(pcms);
-
if (kvm_enabled() && pcmc->kvmclock_enabled) {
kvmclock_create();
}
@@ -113,10 +113,6 @@ static void pc_q35_init(MachineState *machine)
xen_hvm_init(pcms, &ram_memory);
}
- pc_cpus_init(pcms);
-
- kvmclock_create();
-
/* pci enabled */
if (pcmc->pci_enabled) {
pci_memory = g_new(MemoryRegion, 1);
@@ -143,6 +139,13 @@ static void pc_q35_init(MachineState *machine)
rom_memory, &ram_memory);
}
+ pc_cpus_init(pcms);
+ if (!pcmc->has_acpi_build) {
+ /* only machine types 1.7 & older need this */
+ pc_acpi_init("q35-acpi-dsdt.aml");
+ }
+
+ kvmclock_create();
/* irq lines */
gsi_state = g_malloc0(sizeof(*gsi_state));
if (kvm_irqchip_in_kernel()) {
@@ -10,18 +10,18 @@
* later. See the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/apic_internal.h"
#include "hw/pci/msi.h"
#include "hw/xen/xen.h"
-static uint64_t xen_apic_mem_read(void *opaque, hwaddr addr,
- unsigned size)
+static uint64_t xen_msi_region_read(void *opaque, hwaddr addr, unsigned size)
{
return ~(uint64_t)0;
}
-static void xen_apic_mem_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
+static void xen_msi_region_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
{
if (size != sizeof(uint32_t)) {
fprintf(stderr, "Xen: APIC write data size = %d, invalid\n", size);
@@ -31,10 +31,14 @@ static void xen_apic_mem_write(void *opaque, hwaddr addr,
xen_hvm_inject_msi(addr, data);
}
-static const MemoryRegionOps xen_apic_io_ops = {
- .read = xen_apic_mem_read,
- .write = xen_apic_mem_write,
+static const MemoryRegionOps xen_msi_region_ops = {
+ .read = xen_msi_region_read,
+ .write = xen_msi_region_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static void xen_apic_realize(DeviceState *dev, Error **errp)
@@ -42,8 +46,10 @@ static void xen_apic_realize(DeviceState *dev, Error **errp)
APICCommonState *s = APIC_COMMON(dev);
s->vapic_control = 0;
- memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s,
- "xen-apic-msi", APIC_SPACE_SIZE);
+ memory_region_init(&s->io_memory, NULL, "xen-apic", APIC_SPACE_SIZE);
+
+ memory_region_init_io(&s->msi_region, NULL, &xen_msi_region_ops, NULL,
+ "xen-msi", MSI_REGION_SIZE);
msi_supported = true;
}
@@ -732,31 +732,11 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr)
return val;
}
-static void apic_send_msi(hwaddr addr, uint32_t data)
-{
- uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
- uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
- uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
- uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
- uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
- /* XXX: Ignore redirection hint. */
- apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode);
-}
-
static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val)
{
DeviceState *dev;
APICCommonState *s;
int index = (addr >> 4) & 0xff;
- if (addr > 0xfff || !index) {
- /* MSI and MMIO APIC are at the same memory location,
- * but actually not on the global bus: MSI is on PCI bus
- * APIC is connected directly to the CPU.
- * Mapping them on the global bus happens to work because
- * MSI registers are reserved in APIC MMIO and vice versa. */
- apic_send_msi(addr, val);
- return;
- }
dev = cpu_get_current_apic();
if (!dev) {
@@ -856,6 +836,34 @@ static void apic_post_load(APICCommonState *s)
}
}
+static void msi_region_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned size)
+{
+ uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
+ uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;
+ uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
+ uint8_t trigger_mode = (data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
+ uint8_t delivery = (data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x7;
+ /* FIXME: Ignoring redirection hint. */
+
+ apic_deliver_irq(dest, dest_mode, delivery, vector, trigger_mode);
+}
+
+static uint64_t msi_region_read(void *opaque, hwaddr addr, unsigned size)
+{
+ return ~(uint64_t)0;
+}
+
+static const MemoryRegionOps msi_region_ops = {
+ .write = msi_region_write,
+ .read = msi_region_read,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
static const MemoryRegionOps apic_io_ops = {
.old_mmio = {
.read = { apic_mem_readb, apic_mem_readw, apic_mem_readl, },
@@ -868,9 +876,12 @@ static void apic_realize(DeviceState *dev, Error **errp)
{
APICCommonState *s = APIC_COMMON(dev);
- memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
+ memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic",
APIC_SPACE_SIZE);
+ memory_region_init_io(&s->msi_region, NULL, &msi_region_ops, NULL, "msi",
+ MSI_REGION_SIZE);
+
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
local_apics[s->idx] = s;
@@ -19,7 +19,9 @@
*/
#include "qemu/osdep.h"
#include "hw/i386/apic.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/apic_internal.h"
+#include "hw/i386/pc.h"
#include "trace.h"
#include "sysemu/kvm.h"
#include "hw/qdev.h"
@@ -23,6 +23,7 @@
#include "qemu/osdep.h"
#include "monitor/monitor.h"
#include "hw/hw.h"
+#include "hw/i386/apic-msidef.h"
#include "hw/i386/pc.h"
#include "hw/i386/ioapic.h"
#include "hw/i386/ioapic_internal.h"
@@ -49,31 +50,31 @@ extern int ioapic_no;
static void ioapic_service(IOAPICCommonState *s)
{
+ AddressSpace *msi_as = PC_MACHINE(qdev_get_machine())->ioapic_msi_target;
+ 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++) {
mask = 1 << i;
if (s->irr & mask) {
- int coalesce = 0;
entry = s->ioredtbl[i];
if (!(entry & IOAPIC_LVT_MASKED)) {
trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
- dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+ 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;
if (trig_mode == IOAPIC_TRIGGER_EDGE) {
s->irr &= ~mask;
} else {
- coalesce = s->ioredtbl[i] & IOAPIC_LVT_REMOTE_IRR;
s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
}
if (delivery_mode == IOAPIC_DM_EXTINT) {
@@ -81,23 +82,12 @@ static void ioapic_service(IOAPICCommonState *s)
} else {
vector = entry & IOAPIC_VECTOR_MASK;
}
-#ifdef CONFIG_KVM
- if (kvm_irqchip_is_split()) {
- if (trig_mode == IOAPIC_TRIGGER_EDGE) {
- kvm_set_irq(kvm_state, i, 1);
- kvm_set_irq(kvm_state, i, 0);
- } else {
- if (!coalesce) {
- kvm_set_irq(kvm_state, i, 1);
- }
- }
- continue;
- }
-#else
- (void)coalesce;
-#endif
- apic_deliver_irq(dest, dest_mode, delivery_mode, vector,
- trig_mode);
+ addr = MSI_ADDR_BASE | (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(msi_as, addr, data);
}
}
}
@@ -436,6 +436,7 @@ static AddressSpace *q35_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
static void mch_init_dmar(MCHPCIState *mch)
{
+ PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
PCIBus *pci_bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
mch->iommu = INTEL_IOMMU_DEVICE(qdev_create(NULL, TYPE_INTEL_IOMMU_DEVICE));
@@ -445,6 +446,12 @@ static void mch_init_dmar(MCHPCIState *mch)
sysbus_mmio_map(SYS_BUS_DEVICE(mch->iommu), 0, Q35_HOST_BRIDGE_IOMMU_ADDR);
pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
+
+ pcms->ioapic_msi_target = q35_host_dma_iommu(pci_bus, mch->iommu,
+ Q35_PSEUDO_DEVFN_IOAPIC);
+
+ pcms->hpet_msi_target = q35_host_dma_iommu(pci_bus, mch->iommu,
+ Q35_PSEUDO_DEVFN_HPET);
}
static void mch_realize(PCIDevice *d, Error **errp)
@@ -52,6 +52,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
static void pcibus_reset(BusState *qbus);
+static AddressSpace *pci_dma_address_space = &address_space_memory;
static Property pci_props[] = {
DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1),
@@ -2396,6 +2397,11 @@ static void pci_device_class_init(ObjectClass *klass, void *data)
pc->realize = pci_default_realize;
}
+void pci_set_dma_address_space(AddressSpace *dma_address_space)
+{
+ pci_dma_address_space = dma_address_space;
+}
+
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
{
PCIBus *bus = PCI_BUS(dev->bus);
@@ -2407,7 +2413,7 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
if (iommu_bus && iommu_bus->iommu_fn) {
return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, dev->devfn);
}
- return &address_space_memory;
+ return pci_dma_address_space;
}
void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
@@ -208,9 +208,9 @@ static void update_irq(struct HPETTimer *timer, int set)
}
}
} else if (timer_fsb_route(timer)) {
- address_space_stl_le(&address_space_memory, timer->fsb >> 32,
- timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
- NULL);
+ address_space_stl_le(PC_MACHINE(qdev_get_machine())->hpet_msi_target,
+ timer->fsb >> 32, timer->fsb & 0xffffffff,
+ MEMTXATTRS_UNSPECIFIED, NULL);
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask;
/* fold the ICH PIRQ# pin's internal inversion logic into hpet */
@@ -5,6 +5,9 @@
* Intel APIC constants: from include/asm/msidef.h
*/
+#define MSI_ADDR_BASE 0xfee00000
+#define MSI_REGION_SIZE 0x00100000
+
/*
* Shifts for MSI data
*/
@@ -25,6 +28,7 @@
#define MSI_ADDR_REDIRECTION_SHIFT 3
#define MSI_ADDR_DEST_ID_SHIFT 12
+#define MSI_ADDR_DEST_IDX_SHIFT 4
#define MSI_ADDR_DEST_ID_MASK 0x00ffff0
#endif /* HW_APIC_MSIDEF_H */
@@ -154,6 +154,7 @@ struct APICCommonState {
/*< public >*/
MemoryRegion io_memory;
+ MemoryRegion msi_region;
X86CPU *cpu;
uint32_t apicbase;
uint8_t id;
@@ -31,6 +31,7 @@
#define IOAPIC_VERSION 0x11
#define IOAPIC_LVT_DEST_SHIFT 56
+#define IOAPIC_LVT_DEST_IDX_SHIFT 48
#define IOAPIC_LVT_MASKED_SHIFT 16
#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
@@ -36,6 +36,9 @@
/**
* PCMachineState:
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
+ * @dma_address_space: target address space for DMA from I/O devices
+ * @ioapic_msi_target: target address space for IOAPIC interrupt messages
+ * @hpet_msi_target: target address space for HPET interrupt messages
*/
struct PCMachineState {
/*< private >*/
@@ -65,6 +68,9 @@ struct PCMachineState {
/* CPU and apic information: */
bool apic_xrupt_override;
unsigned apic_id_limit;
+ AddressSpace dma_address_space;
+ AddressSpace *ioapic_msi_target;
+ AddressSpace *hpet_msi_target;
/* NUMA information: */
uint64_t numa_nodes;
@@ -74,6 +74,10 @@ typedef struct Q35PCIHost {
#define Q35_MASK(bit, ms_bit, ls_bit) \
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+#define Q35_PSEUDO_BUS_PLATFORM 0xff
+#define Q35_PSEUDO_DEVFN_IOAPIC 0x01
+#define Q35_PSEUDO_DEVFN_HPET 0x02
+
/*
* gmch part
*/
@@ -417,6 +417,8 @@ void pci_bus_get_w64_range(PCIBus *bus, Range *range);
void pci_device_deassert_intx(PCIDevice *dev);
+void pci_set_dma_address_space(AddressSpace *dma_address_space);
+
typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
@@ -23,6 +23,8 @@
#include "sysemu/cpus.h"
#include "kvm_i386.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/apic-msidef.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "qemu/config-file.h"
@@ -2821,6 +2823,7 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
{
APICCommonState *apic;
static bool apic_mmio_map_once;
+ AddressSpace *dma_as;
if (cpu->apic_state == NULL) {
return;
@@ -2836,6 +2839,10 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
MSR_IA32_APICBASE_BASE,
&apic->io_memory,
0x1000);
+
+ dma_as = &PC_MACHINE(qdev_get_machine())->dma_address_space;
+ memory_region_add_subregion_overlap(dma_as->root, MSI_ADDR_BASE,
+ &apic->msi_region, 1);
apic_mmio_map_once = true;
}
}
@@ -1376,7 +1376,7 @@ const char *get_register_name_32(unsigned int reg);
void enable_compat_apic_id_mode(void);
#define APIC_DEFAULT_ADDRESS 0xfee00000
-#define APIC_SPACE_SIZE 0x100000
+#define APIC_SPACE_SIZE 0x1000
void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);