diff mbox

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

Message ID 54dea1e5f71be876d7154ce153a09273a634af2f.1269936879.git.eduard.munteanu@linux360.ro (mailing list archive)
State New, archived
Headers show

Commit Message

Eduard - Gabriel Munteanu March 30, 2010, 8:20 a.m. UTC
None
diff mbox

Patch

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