Re: [Qemu-devel] [V6 3/4] hw/i386: ACPI table for AMD IOMMU
On Sun, Feb 21, 2016 at 9:20 PM, Jan Kiszkawrote: > On 2016-02-21 19:10, David Kiarie wrote: >> Add IVRS table for AMD IOMMU. Generate IVRS or DMAR >> depending on emulated IOMMU >> >> Signed-off-by: David Kiarie >> --- >> hw/i386/acpi-build.c| 208 >> +--- >> include/hw/acpi/acpi-defs.h | 55 >> 2 files changed, 252 insertions(+), 11 deletions(-) >> >> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c >> index 4554eb8..fa1310f 100644 >> --- a/hw/i386/acpi-build.c >> +++ b/hw/i386/acpi-build.c >> @@ -51,6 +51,7 @@ >> #include "hw/pci/pci_bus.h" >> #include "hw/pci-host/q35.h" >> #include "hw/i386/intel_iommu.h" >> +#include "hw/i386/amd_iommu.h" >> #include "hw/timer/hpet.h" >> >> #include "hw/acpi/aml-build.h" >> @@ -121,6 +122,12 @@ typedef struct AcpiBuildPciBusHotplugState { >> bool pcihp_bridge_en; >> } AcpiBuildPciBusHotplugState; >> >> +typedef enum iommu_type { >> +TYPE_AMD, >> +TYPE_INTEL, >> +TYPE_NONE >> +} iommu_type; >> + >> static >> int acpi_add_cpu_info(Object *o, void *opaque) >> { >> @@ -2513,6 +2520,188 @@ build_dmar_q35(GArray *table_data, GArray *linker) >> "DMAR", table_data->len - dmar_start, 1, NULL, NULL); >> } >> >> +static void >> +build_amd_iommu(GArray *table_data, GArray *linker) >> +{ >> +int iommu_start = table_data->len; >> +bool iommu_ambig; >> + >> +AcpiAMDIOMMUIVRS *ivrs; >> +AcpiAMDIOMMUHardwareUnit *iommu; >> + >> +/* IVRS definition */ >> +ivrs = acpi_data_push(table_data, sizeof(*ivrs)); >> +ivrs->revision = cpu_to_le16(ACPI_IOMMU_IVRS_TYPE); >> +ivrs->length = cpu_to_le16((sizeof(*ivrs) + sizeof(*iommu))); >> +ivrs->v_common_info = cpu_to_le64(AMD_IOMMU_HOST_ADDRESS_WIDTH << 8); >> + >> +AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("", >> +TYPE_AMD_IOMMU_DEVICE, _ambig); >> + >> +/* IVDB definition - type 10h */ >> +iommu = acpi_data_push(table_data, sizeof(*iommu)); >> +if (!iommu_ambig) { >> +iommu->type = cpu_to_le16(0x10); >> +/* IVHD flags */ >> +iommu->flags = cpu_to_le16(iommu->flags); >> +iommu->flags = cpu_to_le16(IVHD_HT_TUNEN | IVHD_PPRSUP | >> IVHD_IOTLBSUP >> + | IVHD_PREFSUP); >> +iommu->length = cpu_to_le16(sizeof(*iommu)); >> +iommu->device_id = cpu_to_le16(PCI_DEVICE_ID_RD890_IOMMU); >> +iommu->capability_offset = cpu_to_le16(s->capab_offset); >> +iommu->mmio_base = cpu_to_le64(s->mmio.addr); >> +iommu->pci_segment = 0; >> +iommu->interrupt_info = 0; >> +/* EFR features */ >> +iommu->efr_register = cpu_to_le64(IVHD_EFR_GTSUP | IVHD_EFR_HATS >> + | IVHD_EFR_GATS); >> +iommu->efr_register = cpu_to_le64(iommu->efr_register); >> +/* device entries */ >> +memset(iommu->dev_entries, 0, 20); >> +/* Add device flags here >> + * This is are 4-byte device entries currently reporting the range >> of >> + * devices 00h - h; all devices >> + * >> + * Device setting affecting all devices should be made here >> + * >> + * Refer to >> + * (http://developer.amd.com/wordpress/media/2012/10/488821.pdf) >> + * 5.2.2.1 >> + */ >> +iommu->dev_entries[12] = 3; >> +iommu->dev_entries[16] = 4; >> +iommu->dev_entries[17] = 0xff; >> +iommu->dev_entries[18] = 0xff; >> +} >> + >> +build_header(linker, table_data, (void *)(table_data->data + >> iommu_start), >> + "IVRS", table_data->len - iommu_start, 1, NULL); >> +} >> + >> +static iommu_type has_iommu(void) >> +{ >> +bool ambiguous; >> + >> +if (object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE, ) >> +&& !ambiguous) >> +return TYPE_AMD; >> +else if (object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE, >> ) >> +&& !ambiguous) >> +return TYPE_INTEL; >> +else >> +return TYPE_NONE; >> +} >> + >> +static void >> +build_dsdt(GArray *table_data, GArray *linker, >> + AcpiPmInfo *pm, AcpiMiscInfo *misc) >> +{ >> +Aml *dsdt, *sb_scope, *scope, *dev, *method, *field; >> +MachineState *machine = MACHINE(qdev_get_machine()); >> +uint32_t nr_mem = machine->ram_slots; >> + >> +dsdt = init_aml_allocator(); >> + >> +/* Reserve space for header */ >> +acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); >> + >> +build_dbg_aml(dsdt); >> +if (misc->is_piix4) { >> +sb_scope = aml_scope("_SB"); >> +dev = aml_device("PCI0"); >> +aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); >> +aml_append(dev, aml_name_decl("_ADR", aml_int(0))); >> +aml_append(dev, aml_name_decl("_UID", aml_int(1))); >> +aml_append(sb_scope, dev);
Re: [Qemu-devel] [V6 3/4] hw/i386: ACPI table for AMD IOMMU
On 2016-02-21 19:10, David Kiarie wrote: > Add IVRS table for AMD IOMMU. Generate IVRS or DMAR > depending on emulated IOMMU > > Signed-off-by: David Kiarie> --- > hw/i386/acpi-build.c| 208 > +--- > include/hw/acpi/acpi-defs.h | 55 > 2 files changed, 252 insertions(+), 11 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index 4554eb8..fa1310f 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -51,6 +51,7 @@ > #include "hw/pci/pci_bus.h" > #include "hw/pci-host/q35.h" > #include "hw/i386/intel_iommu.h" > +#include "hw/i386/amd_iommu.h" > #include "hw/timer/hpet.h" > > #include "hw/acpi/aml-build.h" > @@ -121,6 +122,12 @@ typedef struct AcpiBuildPciBusHotplugState { > bool pcihp_bridge_en; > } AcpiBuildPciBusHotplugState; > > +typedef enum iommu_type { > +TYPE_AMD, > +TYPE_INTEL, > +TYPE_NONE > +} iommu_type; > + > static > int acpi_add_cpu_info(Object *o, void *opaque) > { > @@ -2513,6 +2520,188 @@ build_dmar_q35(GArray *table_data, GArray *linker) > "DMAR", table_data->len - dmar_start, 1, NULL, NULL); > } > > +static void > +build_amd_iommu(GArray *table_data, GArray *linker) > +{ > +int iommu_start = table_data->len; > +bool iommu_ambig; > + > +AcpiAMDIOMMUIVRS *ivrs; > +AcpiAMDIOMMUHardwareUnit *iommu; > + > +/* IVRS definition */ > +ivrs = acpi_data_push(table_data, sizeof(*ivrs)); > +ivrs->revision = cpu_to_le16(ACPI_IOMMU_IVRS_TYPE); > +ivrs->length = cpu_to_le16((sizeof(*ivrs) + sizeof(*iommu))); > +ivrs->v_common_info = cpu_to_le64(AMD_IOMMU_HOST_ADDRESS_WIDTH << 8); > + > +AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("", > +TYPE_AMD_IOMMU_DEVICE, _ambig); > + > +/* IVDB definition - type 10h */ > +iommu = acpi_data_push(table_data, sizeof(*iommu)); > +if (!iommu_ambig) { > +iommu->type = cpu_to_le16(0x10); > +/* IVHD flags */ > +iommu->flags = cpu_to_le16(iommu->flags); > +iommu->flags = cpu_to_le16(IVHD_HT_TUNEN | IVHD_PPRSUP | > IVHD_IOTLBSUP > + | IVHD_PREFSUP); > +iommu->length = cpu_to_le16(sizeof(*iommu)); > +iommu->device_id = cpu_to_le16(PCI_DEVICE_ID_RD890_IOMMU); > +iommu->capability_offset = cpu_to_le16(s->capab_offset); > +iommu->mmio_base = cpu_to_le64(s->mmio.addr); > +iommu->pci_segment = 0; > +iommu->interrupt_info = 0; > +/* EFR features */ > +iommu->efr_register = cpu_to_le64(IVHD_EFR_GTSUP | IVHD_EFR_HATS > + | IVHD_EFR_GATS); > +iommu->efr_register = cpu_to_le64(iommu->efr_register); > +/* device entries */ > +memset(iommu->dev_entries, 0, 20); > +/* Add device flags here > + * This is are 4-byte device entries currently reporting the range > of > + * devices 00h - h; all devices > + * > + * Device setting affecting all devices should be made here > + * > + * Refer to > + * (http://developer.amd.com/wordpress/media/2012/10/488821.pdf) > + * 5.2.2.1 > + */ > +iommu->dev_entries[12] = 3; > +iommu->dev_entries[16] = 4; > +iommu->dev_entries[17] = 0xff; > +iommu->dev_entries[18] = 0xff; > +} > + > +build_header(linker, table_data, (void *)(table_data->data + > iommu_start), > + "IVRS", table_data->len - iommu_start, 1, NULL); > +} > + > +static iommu_type has_iommu(void) > +{ > +bool ambiguous; > + > +if (object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE, ) > +&& !ambiguous) > +return TYPE_AMD; > +else if (object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE, > ) > +&& !ambiguous) > +return TYPE_INTEL; > +else > +return TYPE_NONE; > +} > + > +static void > +build_dsdt(GArray *table_data, GArray *linker, > + AcpiPmInfo *pm, AcpiMiscInfo *misc) > +{ > +Aml *dsdt, *sb_scope, *scope, *dev, *method, *field; > +MachineState *machine = MACHINE(qdev_get_machine()); > +uint32_t nr_mem = machine->ram_slots; > + > +dsdt = init_aml_allocator(); > + > +/* Reserve space for header */ > +acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader)); > + > +build_dbg_aml(dsdt); > +if (misc->is_piix4) { > +sb_scope = aml_scope("_SB"); > +dev = aml_device("PCI0"); > +aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03"))); > +aml_append(dev, aml_name_decl("_ADR", aml_int(0))); > +aml_append(dev, aml_name_decl("_UID", aml_int(1))); > +aml_append(sb_scope, dev); > +aml_append(dsdt, sb_scope); > + > +build_hpet_aml(dsdt); > +build_piix4_pm(dsdt); > +build_piix4_isa_bridge(dsdt); > +build_isa_devices_aml(dsdt); > +