[RFC PATCH 5/7] x86-64: AMD IOMMU stub

Eduard - Gabriel Munteanu
2010-03-30T08:20:28Z

This currently loads a non-functional IVRS ACPI table and provides a
skeleton for initializing the AMD IOMMU.

Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
---
Makefile.target | 1 +
hw/amd_iommu.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/pc.c | 2 +
hw/pc.h | 3 ++
4 files changed, 109 insertions(+), 0 deletions(-)
create mode 100644 hw/amd_iommu.c

diff --git a/Makefile.target b/Makefile.target
index cbe19a6..dfa4652 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -230,6 +230,7 @@ obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += extboot.o
obj-i386-y += ne2000-isa.o debugcon.o multiboot.o
obj-i386-y += testdev.o
+obj-i386-y += amd_iommu.o

obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
diff --git a/hw/amd_iommu.c b/hw/amd_iommu.c
new file mode 100644
index 0000000..b502430
--- /dev/null
+++ b/hw/amd_iommu.c
@@ -0,0 +1,103 @@
+/*
+ * AMD IOMMU emulation
+ *
+ * Copyright (c) 2010 Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * IVRS (I/O Virtualization Reporting Structure) table.
+ *
+ * Describes the AMD IOMMU, as per:
+ * "AMD I/O Virtualization Technology (IOMMU) Specification", rev 1.26
+ */
+
+#include <stdint.h>
+
+#include "pc.h"
+
+struct ivrs_ivhd
+{
+ uint8_t type;
+ uint8_t flags;
+ uint16_t length;
+ uint16_t devid;
+ uint16_t capab_off;
+ uint64_t iommu_base_addr;
+ uint16_t pci_seg_group;
+ uint16_t iommu_info;
+ uint32_t reserved;
+ uint32_t entry;
+} __attribute__ ((__packed__));
+
+struct ivrs_table
+{
+ struct acpi_table_header acpi_hdr;
+ uint32_t iv_info;
+ uint32_t reserved[2];
+ struct ivrs_ivhd ivhd;
+} __attribute__ ((__packed__));
+
+static const char ivrs_sig[] = "IVRS";
+static const char dfl_id[] = "QEMUQEMU";
+
+static void amd_iommu_init_ivrs(void)
+{
+ int ivrs_size = sizeof(struct ivrs_table);
+ struct ivrs_table *ivrs;
+ struct ivrs_ivhd *ivhd;
+ struct acpi_table_header *acpi_hdr;
+
+ ivrs = acpi_alloc_table(ivrs_size);
+ acpi_hdr = &ivrs->acpi_hdr;
+ ivhd = &ivrs->ivhd;
+
+ ivrs->iv_info = (64 << 15) | /* Virtual address space size. */
+ (48 << 8); /* Physical address space size. */
+
+ ivhd->type = 0x10;
+ ivhd->flags = 0;
+ ivhd->length = sizeof(struct ivrs_ivhd);
+ ivhd->devid = 0;
+ ivhd->capab_off = 0;
+ ivhd->iommu_base_addr = 0;
+ ivhd->pci_seg_group = 0;
+ ivhd->iommu_info = 0;
+ ivhd->reserved = 0;
+ ivhd->entry = 0;
+
+ strncpy(acpi_hdr->signature, ivrs_sig, 4);
+ acpi_hdr->revision = 1;
+ strncpy(acpi_hdr->oem_id, dfl_id, 6);
+ strncpy(acpi_hdr->oem_table_id, dfl_id, 8);
+ acpi_hdr->oem_revision = 1;
+ strncpy(acpi_hdr->asl_compiler_id, dfl_id, 4);
+ acpi_hdr->asl_compiler_revision = 1;
+
+ acpi_commit_table(ivrs);
+}
+
+int amd_iommu_init(void)
+{
+ amd_iommu_init_ivrs();
+
+ return 0;
+}
+
diff --git a/hw/pc.c b/hw/pc.c
index 0aebae9..89a7a30 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -906,6 +906,8 @@ static void pc_init1(ram_addr_t ram_size,
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);

+ amd_iommu_init();
+
fw_cfg = bochs_bios_init();
rom_set_fw(fw_cfg);

diff --git a/hw/pc.h b/hw/pc.h
index 92954db..b91300e 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -194,4 +194,7 @@ int cpu_is_bsp(CPUState *env);

int e820_add_entry(uint64_t, uint64_t, uint32_t);

+/* amd_iommu.c */
+int amd_iommu_init(void);
+
#endif
--
1.6.4.4