Patchwork [v4,24/28] tools/libacpi: Add new fields in acpi_config for DMAR table

login
register
mail settings
Submitter Chao Gao
Date Nov. 17, 2017, 6:22 a.m.
Message ID <1510899755-40237-25-git-send-email-chao.gao@intel.com>
Download mbox | patch
Permalink /patch/385525/
State New
Headers show

Comments

Chao Gao - Nov. 17, 2017, 6:22 a.m.
The BIOS reports the remapping hardware units in a platform to system software
through the DMA Remapping Reporting (DMAR) ACPI table.
New fields are introduced for DMAR table. These new fields are set by
toolstack through parsing guest's config file. construct_dmar() is added to
build DMAR table according to the new fields.

The header files in ovmf.c are re-ordered to avoid including <stdbool.h> in
tools/libacpi/libacpi.h.

Signed-off-by: Chao Gao <chao.gao@intel.com>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
---
v4:
 - initialize variables during declaration if possible
 - reorder the sequence of header files to avoid including <stdbool.h>
 in tools/libacpi/libacpi.h

v3:
 - Remove chip-set specific IOAPIC BDF. Instead, let IOAPIC-related
 info be passed by struct acpi_config.
---
 tools/firmware/hvmloader/ovmf.c |  2 +-
 tools/libacpi/build.c           | 49 +++++++++++++++++++++++++++++++++++++++++
 tools/libacpi/libacpi.h         |  9 ++++++++
 3 files changed, 59 insertions(+), 1 deletion(-)

Patch

diff --git a/tools/firmware/hvmloader/ovmf.c b/tools/firmware/hvmloader/ovmf.c
index a17a11c..606ab4d 100644
--- a/tools/firmware/hvmloader/ovmf.c
+++ b/tools/firmware/hvmloader/ovmf.c
@@ -23,10 +23,10 @@ 
 
 #include "config.h"
 #include "smbios_types.h"
+#include "util.h"
 #include "libacpi.h"
 #include "apic_regs.h"
 #include "../rombios/config.h"
-#include "util.h"
 #include "pci_regs.h"
 #include "hypercall.h"
 
diff --git a/tools/libacpi/build.c b/tools/libacpi/build.c
index f9881c9..bd759da 100644
--- a/tools/libacpi/build.c
+++ b/tools/libacpi/build.c
@@ -303,6 +303,55 @@  static struct acpi_20_slit *construct_slit(struct acpi_ctxt *ctxt,
     return slit;
 }
 
+/*
+ * Only one DMA remapping hardware unit is exposed and all devices
+ * are under the remapping hardware unit. I/O APIC should be explicitly
+ * enumerated.
+ */
+struct acpi_dmar *construct_dmar(struct acpi_ctxt *ctxt,
+                                 const struct acpi_config *config)
+{
+    struct acpi_dmar_hardware_unit *drhd;
+    struct dmar_device_scope *scope;
+    unsigned int ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
+    unsigned int size = sizeof(struct acpi_dmar) + sizeof(*drhd) +
+                        ioapic_scope_size;
+    struct acpi_dmar *dmar = ctxt->mem_ops.alloc(ctxt, size, 16);
+
+    if ( !dmar )
+        return NULL;
+
+    memset(dmar, 0, size);
+    dmar->header.signature = ACPI_2_0_DMAR_SIGNATURE;
+    dmar->header.revision = ACPI_2_0_DMAR_REVISION;
+    dmar->header.length = size;
+    fixed_strcpy(dmar->header.oem_id, ACPI_OEM_ID);
+    fixed_strcpy(dmar->header.oem_table_id, ACPI_OEM_TABLE_ID);
+    dmar->header.oem_revision = ACPI_OEM_REVISION;
+    dmar->header.creator_id   = ACPI_CREATOR_ID;
+    dmar->header.creator_revision = ACPI_CREATOR_REVISION;
+    dmar->host_address_width = config->host_addr_width - 1;
+    if ( config->iommu_intremap_supported )
+        dmar->flags |= ACPI_DMAR_INTR_REMAP;
+
+    drhd = (struct acpi_dmar_hardware_unit *)((void*)dmar + sizeof(*dmar));
+    drhd->type = ACPI_DMAR_TYPE_DRHD;
+    drhd->length = sizeof(*drhd) + ioapic_scope_size;
+    drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
+    drhd->pci_segment = 0;
+    drhd->base_address = config->iommu_base_addr;
+
+    scope = &drhd->scope[0];
+    scope->type = ACPI_DMAR_DEV_SCOPE_IOAPIC;
+    scope->length = ioapic_scope_size;
+    scope->enumeration_id = config->ioapic_id;
+    scope->bus = config->ioapic_bus;
+    scope->path[0] = config->ioapic_devfn;
+
+    set_checksum(dmar, offsetof(struct acpi_header, checksum), size);
+    return dmar;
+}
+
 static int construct_passthrough_tables(struct acpi_ctxt *ctxt,
                                         unsigned long *table_ptrs,
                                         int nr_tables,
diff --git a/tools/libacpi/libacpi.h b/tools/libacpi/libacpi.h
index a2efd23..c09afdc 100644
--- a/tools/libacpi/libacpi.h
+++ b/tools/libacpi/libacpi.h
@@ -96,8 +96,17 @@  struct acpi_config {
     uint32_t ioapic_base_address;
     uint16_t pci_isa_irq_mask;
     uint8_t ioapic_id;
+
+    /* Emulated IOMMU features, location and IOAPIC under the scope of IOMMU */
+    bool iommu_intremap_supported;
+    uint8_t host_addr_width;
+    uint8_t ioapic_bus;
+    uint16_t ioapic_devfn;
+    uint64_t iommu_base_addr;
 };
 
+struct acpi_dmar *construct_dmar(struct acpi_ctxt *ctxt,
+                                 const struct acpi_config *config);
 int acpi_build_tables(struct acpi_ctxt *ctxt, struct acpi_config *config);
 
 #endif /* __LIBACPI_H__ */