qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 3/4] hw/i386: Introduce IVRS for AMD IOMMU


From: David Kiarie
Subject: [Qemu-devel] [RFC 3/4] hw/i386: Introduce IVRS for AMD IOMMU
Date: Tue, 25 Aug 2015 02:19:28 +0300

From: David <address@hidden>

Add IVRS table for AMD IOMMU. Table indicates that all devices will be
translated by the IOMMU, features common to all IOMMUs and IVDB for the
IOMMU to be emulated

Signed-off-by: David Kiarie <address@hidden>
---
 hw/i386/acpi-build.c        | 85 +++++++++++++++++++++++++++++++++++++++++++++
 include/hw/acpi/acpi-defs.h | 55 +++++++++++++++++++++++++++++
 2 files changed, 140 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..1016ed9 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -50,6 +50,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci-host/q35.h"
 #include "hw/i386/intel_iommu.h"
+#include "hw/i386/amd_iommu.h"
 
 #include "hw/i386/q35-acpi-dsdt.hex"
 #include "hw/i386/acpi-dsdt.hex"
@@ -1576,10 +1577,80 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 static void
+amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
+{
+    uint64_t newvalue = *value | flag;
+    *(uint64_t*)value = newvalue;
+}
+
+static void
+amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
+{
+    uint64_t newvalue = *value | feature;
+    *value = newvalue;
+}
+
+static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+    int iommu_start = table_data->len;
+    bool iommu_ambig;
+    uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
+
+    AcpiAMDIOMMUIVRS *ivrs;
+    AcpiAMDIOMMUHardwareUnit *iommu;
+
+    /* IVRS definition */
+    ivrs = acpi_data_push(table_data, sizeof(*ivrs));
+    ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
+    ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
+    ivrs->v_common_info = host_width;
+
+    AMDIOMMUState *s = (AMDIOMMUState*)object_resolve_path_type("", 
TYPE_AMD_IOMMU_DEVICE, &iommu_ambig);
+
+    /* IVDB definition */
+    iommu = acpi_data_push(table_data, sizeof(*iommu));
+    if(!iommu_ambig){
+        iommu->type = 0x10;
+        /* IVHD flags */
+        amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
+        amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
+        amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
+        amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
+        amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
+
+        iommu->length = sizeof(*iommu);
+        iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
+        iommu->capability_offset = s->capab_offset;
+        iommu->mmio_base = s->mmio.addr;
+        iommu->pci_segment = cpu_to_le16(0);
+        iommu->interrupt_info = cpu_to_le16(0);
+
+        /* EFR features */
+        amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
+        amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
+        amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
+
+        /* device entries */
+        memset(iommu->dev_entries, 0, 20);
+
+        /* Add device flags here */
+        iommu->dev_entries[12] = 3;
+        iommu->dev_entries[16] = 4;
+        iommu->dev_entries[17] = 0xff;
+        iommu->dev_entries[18] = 0xff;
+    }
+
+    build_header(linker, table_data, (void*)(table_data->data + iommu_start),
+                 "IVRS", table_data->len - iommu_start, 1);
+}
+
+static void
 build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
 {
     AcpiTableHeader *dsdt;
 
+
     assert(misc->dsdt_code && misc->dsdt_size);
 
     dsdt = acpi_data_push(table_data, misc->dsdt_size);
@@ -1658,6 +1729,16 @@ static bool acpi_has_iommu(void)
     return intel_iommu && !ambiguous;
 }
 
+static bool acpi_has_amd_iommu(void)
+{
+    bool ambiguous;
+    Object *amd_iommu;
+
+    amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
+                                         &ambiguous);
+    return amd_iommu && !ambiguous;
+}
+
 static
 void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 {
@@ -1741,6 +1822,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
         acpi_add_table(table_offsets, tables_blob);
         build_dmar_q35(tables_blob, tables->linker);
     }
+    if(acpi_has_amd_iommu() && !acpi_has_iommu()){
+        acpi_add_table(table_offsets, tables_blob);
+        build_amd_iommu(tables_blob, tables->linker);
+    }
 
     /* Add tables supplied by user (if any) */
     for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 2b431e6..4fc1f79 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -561,4 +561,59 @@ typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
 /* Masks for Flags field above */
 #define ACPI_DMAR_INCLUDE_PCI_ALL   1
 
+/* IVRS constants */
+#define ACPI_IOMMU_HARDWAREUNIT_TYPE 0x10
+#define ACPI_IOMMU_IVRS_TYPE 0x1
+#define AMD_IOMMU_HOST_ADDRESS_WIDTH 39UL
+
+/* AMD IOMMU IVRS table */
+struct AcpiAMDIOMMUIVRS{
+    ACPI_TABLE_HEADER_DEF
+    uint32_t v_common_info; /* common virtualization information */
+    uint64_t reserved;      /* reserved                          */
+} QEMU_PACKED;
+typedef struct AcpiAMDIOMMUIVRS AcpiAMDIOMMUIVRS;
+
+/* flags in the IVHD headers */
+#define IVHD_HT_TUNEN    (1UL << 0)
+#define IVHD_PASS_PW     (1UL << 1)
+#define IVHD_RESPASS_PW  (1UL << 2)
+#define IVHD_ISOC        (1UL << 3)
+#define IVHD_IOTLBSUP    (1UL << 4)
+#define IVHD_COHERENT    (1UL << 5)
+#define IVHD_PREFSUP     (1UL << 6)
+#define IVHD_PPRSUP      (1UL << 7)
+
+/* features in the IVHD headers */
+#define IVHD_EFR_HATS       48
+#define IVHD_EFR_GATS       48
+#define IVHD_EFR_MSI_NUM
+#define IVHD_EFR_PNBANKS
+#define IVHD_EFR_PNCOUNTERS
+#define IVHD_EFR_PASMAX
+#define IVHD_EFR_HESUP  (1UL << 7)
+#define IVHD_EFR_GASUP  (1UL << 6)
+#define IVHD_EFR_IASUP  (1UL << 5)
+#define IVHD_EFR_GLXSUP (3UL << 3)
+#define IVHD_EFR_GTSUP  (1UL << 2)
+#define IVHD_EFR_NXSUP  (1UL << 1)
+#define IVHD_EFR_XTSUP  (1UL << 0)
+
+/* IVDB type 10h */
+struct AcpiAMDIOMMUHardwareUnit{
+ uint8_t type;
+ uint8_t flags;
+ uint16_t length;
+ uint16_t device_id;
+ uint16_t capability_offset;
+ uint64_t mmio_base;
+ uint16_t pci_segment;
+ uint16_t interrupt_info;
+ uint32_t features;
+ uint64_t efr_register;
+ uint64_t reserved;
+ uint8_t dev_entries[20];
+}QEMU_PACKED;
+typedef struct AcpiAMDIOMMUHardwareUnit AcpiAMDIOMMUHardwareUnit;
+
 #endif
-- 
2.1.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]