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

Blue Swirl
2010-03-30T20:37:38Z

On 3/30/10, Eduard - Gabriel Munteanu <eduard.munteanu@linux360.ro> wrote:
> 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;

The table would be filled with wrong data on big endian host. Please
use cpu_to_le64/32/16.

> + 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
>
>
>
>