aboutsummaryrefslogtreecommitdiff
path: root/hw/i386/acpi-build.c
diff options
context:
space:
mode:
authorBui Quang Minh <minhquangbui99@gmail.com>2024-01-11 22:44:03 +0700
committerMichael S. Tsirkin <mst@redhat.com>2024-02-14 06:09:32 -0500
commit328a11a08a70ca9e565cee807eb74e1e59e1b5d9 (patch)
tree833e1c3b1714887ee3a1961699fa6dd1cbc7f343 /hw/i386/acpi-build.c
parent595cd6fd9dffe51ef3fdb3077979a87ff2947b1f (diff)
downloadqemu-328a11a08a70ca9e565cee807eb74e1e59e1b5d9.zip
qemu-328a11a08a70ca9e565cee807eb74e1e59e1b5d9.tar.gz
qemu-328a11a08a70ca9e565cee807eb74e1e59e1b5d9.tar.bz2
amd_iommu: report x2APIC support to the operating system
This commit adds XTSup configuration to let user choose to whether enable this feature or not. When XTSup is enabled, additional bytes in IRTE with enabled guest virtual VAPIC are used to support 32-bit destination id. Additionally, this commit exports IVHD type 0x11 besides the old IVHD type 0x10 in ACPI table. IVHD type 0x10 does not report full set of IOMMU features only the legacy ones, so operating system (e.g. Linux) may only detects x2APIC support if IVHD type 0x11 is available. The IVHD type 0x10 is kept so that old operating system that only parses type 0x10 can detect the IOMMU device. Besides, an amd_iommu-stub.c file is created to provide the definition for amdvi_extended_feature_register when CONFIG_AMD_IOMMU=n. This function is used by acpi-build.c to get the extended feature register value for building the ACPI table. When CONFIG_AMD_IOMMU=y, this function is defined in amd_iommu.c. Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com> Message-Id: <20240111154404.5333-7-minhquangbui99@gmail.com> Acked-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.c105
1 files changed, 68 insertions, 37 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e990b0a..d5c6c94 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2333,30 +2333,23 @@ static void
build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
const char *oem_table_id)
{
- int ivhd_table_len = 24;
AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
GArray *ivhd_blob = g_array_new(false, true, 1);
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
.oem_table_id = oem_table_id };
+ uint64_t feature_report;
acpi_table_begin(&table, table_data);
/* IVinfo - IO virtualization information common to all
* 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 */
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
* 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);
}
- ivhd_table_len += ivhd_blob->len;
-
/*
* 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())) {
- 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 */
- build_append_int_noprefix(table_data, ivhd_table_len, 2);
+ build_append_int_noprefix(table_data, ivhd_blob->len + 24, 2);
/* DeviceID */
build_append_int_noprefix(table_data,
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 */
build_append_int_noprefix(table_data, 0, 2);
/* 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,
- (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 */
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);
}