|
@@ -2333,30 +2333,23 @@ static void
|
|
build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
|
build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
|
const char *oem_table_id)
|
|
const char *oem_table_id)
|
|
{
|
|
{
|
|
- int ivhd_table_len = 24;
|
|
|
|
AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
|
|
AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
|
|
GArray *ivhd_blob = g_array_new(false, true, 1);
|
|
GArray *ivhd_blob = g_array_new(false, true, 1);
|
|
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
|
|
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
|
|
.oem_table_id = oem_table_id };
|
|
.oem_table_id = oem_table_id };
|
|
|
|
+ uint64_t feature_report;
|
|
|
|
|
|
acpi_table_begin(&table, table_data);
|
|
acpi_table_begin(&table, table_data);
|
|
/* IVinfo - IO virtualization information common to all
|
|
/* IVinfo - IO virtualization information common to all
|
|
* IOMMU units in a system
|
|
* IOMMU units in a system
|
|
*/
|
|
*/
|
|
- build_append_int_noprefix(table_data, 40UL << 8/* PASize */, 4);
|
|
|
|
|
|
+ build_append_int_noprefix(table_data,
|
|
|
|
+ (1UL << 0) | /* EFRSup */
|
|
|
|
+ (40UL << 8), /* PASize */
|
|
|
|
+ 4);
|
|
/* reserved */
|
|
/* reserved */
|
|
build_append_int_noprefix(table_data, 0, 8);
|
|
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);
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* A PCI bus walk, for each PCI host bridge, is necessary to create a
|
|
* A PCI bus walk, for each PCI host bridge, is necessary to create a
|
|
* complete set of IVHD entries. Do this into a separate blob so that we
|
|
* complete set of IVHD entries. Do this into a separate blob so that we
|
|
@@ -2376,18 +2369,34 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
|
build_append_int_noprefix(ivhd_blob, 0x0000001, 4);
|
|
build_append_int_noprefix(ivhd_blob, 0x0000001, 4);
|
|
}
|
|
}
|
|
|
|
|
|
- ivhd_table_len += ivhd_blob->len;
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* When interrupt remapping is supported, we add a special IVHD device
|
|
* When interrupt remapping is supported, we add a special IVHD device
|
|
- * for type IO-APIC.
|
|
|
|
|
|
+ * for type IO-APIC
|
|
|
|
+ * Refer to spec - Table 95: IVHD device entry type codes
|
|
|
|
+ *
|
|
|
|
+ * Linux IOMMU driver checks for the special IVHD device (type IO-APIC).
|
|
|
|
+ * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059'
|
|
*/
|
|
*/
|
|
if (x86_iommu_ir_supported(x86_iommu_get_default())) {
|
|
if (x86_iommu_ir_supported(x86_iommu_get_default())) {
|
|
- ivhd_table_len += 8;
|
|
|
|
|
|
+ build_append_int_noprefix(ivhd_blob,
|
|
|
|
+ (0x1ull << 56) | /* type IOAPIC */
|
|
|
|
+ (IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */
|
|
|
|
+ 0x48, /* special device */
|
|
|
|
+ 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 */
|
|
/* IVHD length */
|
|
- build_append_int_noprefix(table_data, ivhd_table_len, 2);
|
|
|
|
|
|
+ build_append_int_noprefix(table_data, ivhd_blob->len + 24, 2);
|
|
/* DeviceID */
|
|
/* DeviceID */
|
|
build_append_int_noprefix(table_data,
|
|
build_append_int_noprefix(table_data,
|
|
object_property_get_int(OBJECT(&s->pci), "addr",
|
|
object_property_get_int(OBJECT(&s->pci), "addr",
|
|
@@ -2401,31 +2410,53 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
|
/* IOMMU info */
|
|
/* IOMMU info */
|
|
build_append_int_noprefix(table_data, 0, 2);
|
|
build_append_int_noprefix(table_data, 0, 2);
|
|
/* IOMMU Feature Reporting */
|
|
/* IOMMU Feature Reporting */
|
|
|
|
+ feature_report = (48UL << 30) | /* HATS */
|
|
|
|
+ (48UL << 28) | /* GATS */
|
|
|
|
+ (1UL << 2) | /* GTSup */
|
|
|
|
+ (1UL << 6); /* GASup */
|
|
|
|
+ if (s->xtsup) {
|
|
|
|
+ feature_report |= (1UL << 0); /* XTSup */
|
|
|
|
+ }
|
|
|
|
+ build_append_int_noprefix(table_data, feature_report, 4);
|
|
|
|
+
|
|
|
|
+ /* IVHD entries as found above */
|
|
|
|
+ g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len);
|
|
|
|
+
|
|
|
|
+ /* IVHD definition - type 11h */
|
|
|
|
+ build_append_int_noprefix(table_data, 0x11, 1);
|
|
|
|
+ /* virtualization flags */
|
|
build_append_int_noprefix(table_data,
|
|
build_append_int_noprefix(table_data,
|
|
- (48UL << 30) | /* HATS */
|
|
|
|
- (48UL << 28) | /* GATS */
|
|
|
|
- (1UL << 2) | /* GTSup */
|
|
|
|
- (1UL << 6), /* GASup */
|
|
|
|
- 4);
|
|
|
|
|
|
+ (1UL << 0) | /* HtTunEn */
|
|
|
|
+ (1UL << 4), /* iotblSup */
|
|
|
|
+ 1);
|
|
|
|
+
|
|
|
|
+ /* IVHD length */
|
|
|
|
+ build_append_int_noprefix(table_data, ivhd_blob->len + 40, 2);
|
|
|
|
+ /* DeviceID */
|
|
|
|
+ build_append_int_noprefix(table_data,
|
|
|
|
+ object_property_get_int(OBJECT(&s->pci), "addr",
|
|
|
|
+ &error_abort), 2);
|
|
|
|
+ /* Capability offset */
|
|
|
|
+ build_append_int_noprefix(table_data, s->pci.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 Attributes */
|
|
|
|
+ build_append_int_noprefix(table_data, 0, 4);
|
|
|
|
+ /* EFR Register Image */
|
|
|
|
+ build_append_int_noprefix(table_data,
|
|
|
|
+ amdvi_extended_feature_register(s),
|
|
|
|
+ 8);
|
|
|
|
+ /* EFR Register Image 2 */
|
|
|
|
+ build_append_int_noprefix(table_data, 0, 8);
|
|
|
|
|
|
/* IVHD entries as found above */
|
|
/* IVHD entries as found above */
|
|
g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len);
|
|
g_array_append_vals(table_data, ivhd_blob->data, ivhd_blob->len);
|
|
- g_array_free(ivhd_blob, TRUE);
|
|
|
|
|
|
|
|
- /*
|
|
|
|
- * Add a special IVHD device type.
|
|
|
|
- * Refer to spec - Table 95: IVHD device entry type codes
|
|
|
|
- *
|
|
|
|
- * Linux IOMMU driver checks for the special IVHD device (type IO-APIC).
|
|
|
|
- * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059'
|
|
|
|
- */
|
|
|
|
- if (x86_iommu_ir_supported(x86_iommu_get_default())) {
|
|
|
|
- build_append_int_noprefix(table_data,
|
|
|
|
- (0x1ull << 56) | /* type IOAPIC */
|
|
|
|
- (IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */
|
|
|
|
- 0x48, /* special device */
|
|
|
|
- 8);
|
|
|
|
- }
|
|
|
|
|
|
+ g_array_free(ivhd_blob, TRUE);
|
|
acpi_table_end(linker, &table);
|
|
acpi_table_end(linker, &table);
|
|
}
|
|
}
|
|
|
|
|