summaryrefslogtreecommitdiffstats
path: root/hw/i386/acpi-build.c
diff options
context:
space:
mode:
authorLe Tan2014-08-16 07:55:39 +0200
committerMichael S. Tsirkin2014-08-28 23:10:22 +0200
commitd4eb911935640139eef7f1dd5cf9db7141578554 (patch)
treed3e27d60c378c6e9391eb19b388423a7fd7f1350 /hw/i386/acpi-build.c
parentintel-iommu: introduce Intel IOMMU (VT-d) emulation (diff)
downloadqemu-d4eb911935640139eef7f1dd5cf9db7141578554.tar.gz
qemu-d4eb911935640139eef7f1dd5cf9db7141578554.tar.xz
qemu-d4eb911935640139eef7f1dd5cf9db7141578554.zip
intel-iommu: add DMAR table to ACPI tables
Expose Intel IOMMU to the BIOS. If object of TYPE_INTEL_IOMMU_DEVICE exists, add DMAR table to ACPI RSDT table. For now the DMAR table indicates that there is only one hardware unit without INTR_REMAP capability on the platform. Signed-off-by: Le Tan <tamlokveer@gmail.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386/acpi-build.c')
-rw-r--r--hw/i386/acpi-build.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 85e58347ce..3e7fba3822 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -49,6 +49,7 @@
#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/q35-acpi-dsdt.hex"
#include "hw/i386/acpi-dsdt.hex"
@@ -1388,6 +1389,30 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
}
static void
+build_dmar_q35(GArray *table_data, GArray *linker)
+{
+ int dmar_start = table_data->len;
+
+ AcpiTableDmar *dmar;
+ AcpiDmarHardwareUnit *drhd;
+
+ 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 Remapping Hardware Unit Definition structure */
+ drhd = acpi_data_push(table_data, sizeof(*drhd));
+ drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
+ drhd->length = cpu_to_le16(sizeof(*drhd)); /* No device scope now */
+ drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
+ drhd->pci_segment = cpu_to_le16(0);
+ drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
+
+ build_header(linker, table_data, (void *)(table_data->data + dmar_start),
+ "DMAR", table_data->len - dmar_start, 1);
+}
+
+static void
build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
{
AcpiTableHeader *dsdt;
@@ -1508,6 +1533,16 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
return true;
}
+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;
+}
+
static
void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
{
@@ -1584,6 +1619,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables->table_data);
build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
}
+ if (acpi_has_iommu()) {
+ acpi_add_table(table_offsets, tables->table_data);
+ build_dmar_q35(tables->table_data, tables->linker);
+ }
/* Add tables supplied by user (if any) */
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {