aboutsummaryrefslogtreecommitdiff
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.c76
1 files changed, 67 insertions, 9 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 433febafdd..c20bc71a67 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -59,7 +59,8 @@
#include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h"
-#include "hw/i386/x86-iommu.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
#include "hw/acpi/ipmi.h"
@@ -2562,6 +2563,62 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker)
build_header(linker, table_data, (void *)(table_data->data + dmar_start),
"DMAR", table_data->len - dmar_start, 1, NULL, NULL);
}
+/*
+ * IVRS table as specified in AMD IOMMU Specification v2.62, Section 5.2
+ * accessible here http://support.amd.com/TechDocs/48882_IOMMU.pdf
+ */
+static void
+build_amd_iommu(GArray *table_data, BIOSLinker *linker)
+{
+ int iommu_start = table_data->len;
+ AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
+
+ /* IVRS header */
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
+ /* IVinfo - IO virtualization information common to all
+ * IOMMU units in a system
+ */
+ build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4);
+ /* reserved */
+ build_append_int_noprefix(table_data, 0, 8);
+
+ /* IVHD definition - type 10h */
+ build_append_int_noprefix(table_data, 0x10, 1);
+ /* virtualization flags */
+ build_append_int_noprefix(table_data,
+ (1UL << 0) | /* HtTunEn */
+ (1UL << 4) | /* iotblSup */
+ (1UL << 6) | /* PrefSup */
+ (1UL << 7), /* PPRSup */
+ 1);
+ /* IVHD length */
+ build_append_int_noprefix(table_data, 0x24, 2);
+ /* DeviceID */
+ build_append_int_noprefix(table_data, s->devid, 2);
+ /* Capability offset */
+ build_append_int_noprefix(table_data, s->capab_offset, 2);
+ /* IOMMU base address */
+ build_append_int_noprefix(table_data, s->mmio.addr, 8);
+ /* PCI Segment Group */
+ build_append_int_noprefix(table_data, 0, 2);
+ /* IOMMU info */
+ build_append_int_noprefix(table_data, 0, 2);
+ /* IOMMU Feature Reporting */
+ build_append_int_noprefix(table_data,
+ (48UL << 30) | /* HATS */
+ (48UL << 28) | /* GATS */
+ (1UL << 2), /* GTSup */
+ 4);
+ /*
+ * Type 1 device entry reporting all devices
+ * These are 4-byte device entries currently reporting the range of
+ * Refer to Spec - Table 95:IVHD Device Entry Type Codes(4-byte)
+ */
+ build_append_int_noprefix(table_data, 0x0000001, 4);
+
+ build_header(linker, table_data, (void *)(table_data->data + iommu_start),
+ "IVRS", table_data->len - iommu_start, 1, NULL, NULL);
+}
static GArray *
build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
@@ -2622,11 +2679,6 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
return true;
}
-static bool acpi_has_iommu(void)
-{
- return !!x86_iommu_get_default();
-}
-
static
void acpi_build(AcpiBuildTables *tables, MachineState *machine)
{
@@ -2706,9 +2758,15 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_add_table(table_offsets, tables_blob);
build_mcfg_q35(tables_blob, tables->linker, &mcfg);
}
- if (acpi_has_iommu()) {
- acpi_add_table(table_offsets, tables_blob);
- build_dmar_q35(tables_blob, tables->linker);
+ if (x86_iommu_get_default()) {
+ IommuType IOMMUType = x86_iommu_get_type();
+ if (IOMMUType == TYPE_AMD) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_amd_iommu(tables_blob, tables->linker);
+ } else if (IOMMUType == TYPE_INTEL) {
+ acpi_add_table(table_offsets, tables_blob);
+ build_dmar_q35(tables_blob, tables->linker);
+ }
}
if (pcms->acpi_nvdimm_state.is_enabled) {
nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,