[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [V15 4/4] hw/i386: AMD IOMMU IVRS table
From: |
David Kiarie |
Subject: |
[Qemu-devel] [V15 4/4] hw/i386: AMD IOMMU IVRS table |
Date: |
Tue, 2 Aug 2016 11:39:07 +0300 |
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU.
Signed-off-by: David Kiarie <address@hidden>
---
hw/acpi/aml-build.c | 2 +-
hw/i386/acpi-build.c | 76 ++++++++++++++++++++++++++++++++++++++++-----
hw/i386/x86-iommu.c | 19 ++++++++++++
include/hw/acpi/aml-build.h | 1 +
include/hw/i386/x86-iommu.h | 11 +++++++
5 files changed, 101 insertions(+), 8 deletions(-)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index db3e914..b2a1e40 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -226,7 +226,7 @@ static void build_extop_package(GArray *package, uint8_t op)
build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
}
-static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+void build_append_int_noprefix(GArray *table, uint64_t value, int size)
{
int i;
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a26a4bb..efed318 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,68 @@ 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());
+ assert(s);
+
+ /* 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, 0x28, 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);
+ /* Add device flags here
+ * These are 4-byte device entries currently reporting the range of
+ * devices 00h - ffffh; all devices
+ * Device setting affecting all devices should be made here
+ *
+ * Refer to Spec - Table 95:IVHD Device Entry Type Codes(4-byte)
+ */
+ /* start of device range, 4-byte entries */
+ build_append_int_noprefix(table_data, 0x00000003, 4);
+ /* end of device range */
+ build_append_int_noprefix(table_data, 0x00ffff04, 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 +2685,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)
{
@@ -2639,6 +2697,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState
*machine)
AcpiMcfgInfo mcfg;
Range pci_hole, pci_hole64;
uint8_t *u;
+ IommuType IOMMUType = x86_iommu_get_type();
size_t aml_len = 0;
GArray *tables_blob = tables->table_data;
AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
@@ -2706,7 +2765,10 @@ 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()) {
+ 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);
}
diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c
index ce26b2a..893d54d 100644
--- a/hw/i386/x86-iommu.c
+++ b/hw/i386/x86-iommu.c
@@ -20,7 +20,10 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/boards.h"
+#include "hw/i386/intel_iommu.h"
+#include "hw/i386/amd_iommu.h"
#include "hw/i386/x86-iommu.h"
+#include "sysemu/kvm.h"
#include "qemu/error-report.h"
#include "trace.h"
@@ -71,6 +74,21 @@ X86IOMMUState *x86_iommu_get_default(void)
return x86_iommu_default;
}
+IommuType x86_iommu_get_type(void)
+{
+ bool ambiguous;
+
+ if (object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE, &ambiguous)
+ && !ambiguous) {
+ return TYPE_AMD;
+ } else if (object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE,
&ambiguous)
+ && !ambiguous) {
+ return TYPE_INTEL;
+ } else {
+ return TYPE_NONE;
+ }
+}
+
static void x86_iommu_realize(DeviceState *dev, Error **errp)
{
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(dev);
@@ -79,6 +97,7 @@ static void x86_iommu_realize(DeviceState *dev, Error **errp)
if (x86_class->realize) {
x86_class->realize(dev, errp);
}
+
x86_iommu_set_default(X86_IOMMU_DEVICE(dev));
}
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index e5f0878..559326c 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -367,6 +367,7 @@ Aml *aml_sizeof(Aml *arg);
Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
Aml *aml_object_type(Aml *object);
+void build_append_int_noprefix(GArray *table, uint64_t value, int size);
void
build_header(BIOSLinker *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/include/hw/i386/x86-iommu.h b/include/hw/i386/x86-iommu.h
index c48e8dd..2acc04a 100644
--- a/include/hw/i386/x86-iommu.h
+++ b/include/hw/i386/x86-iommu.h
@@ -37,6 +37,12 @@
typedef struct X86IOMMUState X86IOMMUState;
typedef struct X86IOMMUClass X86IOMMUClass;
+typedef enum IommuType {
+ TYPE_INTEL,
+ TYPE_AMD,
+ TYPE_NONE
+} IommuType;
+
struct X86IOMMUClass {
SysBusDeviceClass parent;
/* Intel/AMD specific realize() hook */
@@ -76,6 +82,11 @@ struct X86IOMMUState {
*/
X86IOMMUState *x86_iommu_get_default(void);
+/*
+ * x86_iommu_get_type - get IOMMU type
+ */
+IommuType x86_iommu_get_type(void);
+
/**
* x86_iommu_iec_register_notifier - register IEC (Interrupt Entry
* Cache) notifiers
--
2.1.4
- [Qemu-devel] [V15 0/4] AMD IOMMU, David Kiarie, 2016/08/02
- [Qemu-devel] [V15 1/4] hw/pci: Prepare for AMD IOMMU, David Kiarie, 2016/08/02
- [Qemu-devel] [V15 2/4] hw/i386/trace-events: Add AMD IOMMU trace events, David Kiarie, 2016/08/02
- [Qemu-devel] [V15 4/4] hw/i386: AMD IOMMU IVRS table,
David Kiarie <=
- [Qemu-devel] [V15 3/4] hw/i386: Introduce AMD IOMMU, David Kiarie, 2016/08/02
- Re: [Qemu-devel] [V15 3/4] hw/i386: Introduce AMD IOMMU, Peter Xu, 2016/08/09
- Re: [Qemu-devel] [V15 3/4] hw/i386: Introduce AMD IOMMU, David Kiarie, 2016/08/10