summaryrefslogtreecommitdiff
path: root/hw/i386/acpi-build.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i386/acpi-build.c')
-rw-r--r--hw/i386/acpi-build.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index fbba461a87..77c40d92e2 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -52,13 +52,14 @@
#include "hw/i386/ich9.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci-host/q35.h"
-#include "hw/i386/intel_iommu.h"
+#include "hw/i386/x86-iommu.h"
#include "hw/timer/hpet.h"
#include "hw/acpi/aml-build.h"
#include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h"
+#include "hw/i386/x86-iommu.h"
#include "hw/acpi/ipmi.h"
@@ -80,6 +81,9 @@
#define ACPI_BUILD_DPRINTF(fmt, ...)
#endif
+/* Default IOAPIC ID */
+#define ACPI_BUILD_IOAPIC_ID 0x0
+
typedef struct AcpiMcfgInfo {
uint64_t mcfg_base;
uint32_t mcfg_size;
@@ -383,7 +387,6 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
io_apic = acpi_data_push(table_data, sizeof *io_apic);
io_apic->type = ACPI_APIC_IO;
io_apic->length = sizeof(*io_apic);
-#define ACPI_BUILD_IOAPIC_ID 0x0
io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
io_apic->interrupt = cpu_to_le32(0);
@@ -2454,6 +2457,10 @@ build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
}
+/*
+ * VT-d spec 8.1 DMA Remapping Reporting Structure
+ * (version Oct. 2014 or later)
+ */
static void
build_dmar_q35(GArray *table_data, BIOSLinker *linker)
{
@@ -2461,19 +2468,38 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker)
AcpiTableDmar *dmar;
AcpiDmarHardwareUnit *drhd;
+ uint8_t dmar_flags = 0;
+ X86IOMMUState *iommu = x86_iommu_get_default();
+ AcpiDmarDeviceScope *scope = NULL;
+ /* Root complex IOAPIC use one path[0] only */
+ size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
+
+ assert(iommu);
+ if (iommu->intr_supported) {
+ dmar_flags |= 0x1; /* Flags: 0x1: INT_REMAP */
+ }
dmar = acpi_data_push(table_data, sizeof(*dmar));
dmar->host_address_width = VTD_HOST_ADDRESS_WIDTH - 1;
- dmar->flags = 0; /* No intr_remap for now */
+ dmar->flags = dmar_flags;
/* DMAR Remapping Hardware Unit Definition structure */
- drhd = acpi_data_push(table_data, sizeof(*drhd));
+ drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
- drhd->length = cpu_to_le16(sizeof(*drhd)); /* No device scope now */
+ drhd->length = cpu_to_le16(sizeof(*drhd) + ioapic_scope_size);
drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
drhd->pci_segment = cpu_to_le16(0);
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
+ /* Scope definition for the root-complex IOAPIC. See VT-d spec
+ * 8.3.1 (version Oct. 2014 or later). */
+ scope = &drhd->scope[0];
+ scope->entry_type = 0x03; /* Type: 0x03 for IOAPIC */
+ scope->length = ioapic_scope_size;
+ scope->enumeration_id = ACPI_BUILD_IOAPIC_ID;
+ scope->bus = Q35_PSEUDO_BUS_PLATFORM;
+ scope->path[0] = cpu_to_le16(Q35_PSEUDO_DEVFN_IOAPIC);
+
build_header(linker, table_data, (void *)(table_data->data + dmar_start),
"DMAR", table_data->len - dmar_start, 1, NULL, NULL);
}
@@ -2539,12 +2565,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
static bool acpi_has_iommu(void)
{
- bool ambiguous;
- Object *intel_iommu;
-
- intel_iommu = object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE,
- &ambiguous);
- return intel_iommu && !ambiguous;
+ return !!x86_iommu_get_default();
}
static