Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-21 Thread Jan Kiszka
On 2016-02-17 20:09, David Kiarie wrote:
> Add IVRS table for AMD IO MMU. Also reverve MMIO
> region for IO MMU via ACPI
> 
> Signed-off-by: David Kiarie 
> ---
>  hw/i386/acpi-build.c| 98 
> -
>  include/hw/acpi/acpi-defs.h | 55 +
>  2 files changed, 142 insertions(+), 11 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 739cfa3..b8cd091 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)
>  {
> @@ -2423,6 +2430,78 @@ build_dmar_q35(GArray *table_data, GArray *linker)
>  }
>  
>  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, &iommu_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);

Requires rebasing over master (to append another NULL here).

Jan



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-17 Thread David Kiarie
Add IVRS table for AMD IO MMU. Also reverve MMIO
region for IO MMU via ACPI

Signed-off-by: David Kiarie 
---
 hw/i386/acpi-build.c| 98 -
 include/hw/acpi/acpi-defs.h | 55 +
 2 files changed, 142 insertions(+), 11 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 739cfa3..b8cd091 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)
 {
@@ -2423,6 +2430,78 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 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, &iommu_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)
+&& !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
 build_dsdt(GArray *table_data, GArray *linker,
AcpiPmInfo *pm, AcpiMiscInfo *misc)
 {
@@ -2590,16 +2669,6 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
 return true;
 }
 
-static bool acpi_has_iommu(void)
-{
-bool ambiguous;
-Object *intel_iommu;
-
-intel_iommu = object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE,
-   &ambiguous);
-return intel_iommu && !ambiguous;
-}
-
 static bool acpi_has_nvdimm(void)
 {
 PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
@@ -2618,6 +2687,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
 AcpiMcfgInfo mcfg;
 PcPciInfo pci;
 uint8_t *u;
+iommu_type type = has_iommu();
 size_t aml_len = 0;
 GArray *tables_blob = tables->table_data;
 
@@ -2685,7 +2755,13 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
 acpi_add_table(table_offsets, tables_blob);
 build_mcfg_q35(tables_blob, tables->linker, &mcfg);
 }
-if (acpi_has_iommu()) {
+
+if (type == TYPE_AMD) {
+acpi_add_table(table_offsets, tables_blob);
+build_amd_iommu(tables_blob, tables->linker);
+}
+
+if (type == TYPE_INTEL) {
 acpi_add_table(table_offsets, tables_blob);
 build_dmar_q35(tables_blob, tables->linke

Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread David kiarie
On Sun, Feb 14, 2016 at 4:07 PM, Michael S. Tsirkin  wrote:
> On Sun, Feb 14, 2016 at 02:54:36PM +0200, Marcel Apfelbaum wrote:
>> On 01/18/2016 05:25 PM, David Kiarie wrote:
>> >Add IVRS table for AMD IO MMU.
>> >
>> >Signed-off-by: David Kiarie 
>> >---
>> >  hw/i386/acpi-build.c| 70 
>> > +
>> >  include/hw/acpi/acpi-defs.h | 55 +++
>> >  2 files changed, 125 insertions(+)
>> >
>> >diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> >index 78758e2..5c0d6b7 100644
>> >--- a/hw/i386/acpi-build.c
>> >+++ b/hw/i386/acpi-build.c
>> >@@ -52,6 +52,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"
>> >@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
>> >  }
>> >
>> >  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, &iommu_ambig);
>> >+
>> >+/* IVDB definition */
>> >+iommu = acpi_data_push(table_data, sizeof(*iommu));
>> >+if (!iommu_ambig) {
>>
>> Hi,
>>
>> If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
>> I think we should report the error to user, something like error_report.
>>
>> >+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
>> >+ *  create entries for devices to be treated specially by IO MMU,
>> >+ *  currently we report all devices to IO MMU with no special flags
>> >+ *  DTE settings made here apply to all devices
>> >+ *  Refer to AMD IOMMU spec Table 97
>> >+ */
>> >+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 bool acpi_has_amd_iommu(void)
>> >+{
>> >+bool ambiguous;
>> >+Object *amd_iommu;
>> >+
>> >+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
>> >+ &ambiguous);
>> >+return amd_iommu && !ambiguous;
>> >+}
>> >+
>> >+static void
>> >  build_dsdt(GArray *table_data, GArray *linker,
>> > AcpiPmInfo *pm, AcpiMiscInfo *misc)
>> >  {
>> >@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, 
>> >AcpiBuildTables *tables)
>> >  build_dmar_q35(tables_blob, tables->linker);
>> >  }
>> >
>> >+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {
>>
>> Since we have the acpi_has_amd_iommu function now, maybe is time to rename
>> acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu 
>> that
>> returns an enum type (NONE/INTEL/AMD).
>>
>> By the way, do we really need to check !acpi_has_iommu() if there is
>> an AMD IOMMU in the system? Having both in the same system is a not (yet) 
>> supported configuration,
>> right?
>>
>> Thanks,
>> Marcel
>>
>
> Long term the right thing to do is to add description
> for each IOMMU present in the system.
> For example, we might have multiple intel iommus.

Yeah, we could have multiple AMD IO MMUs in a system too but I don't
see a generic way to add multiple descriptions since they could have
different settings.

>
>> >+acpi_add_table(table_offsets, tables_blob);

Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread Michael S. Tsirkin
On Sun, Feb 14, 2016 at 02:54:36PM +0200, Marcel Apfelbaum wrote:
> On 01/18/2016 05:25 PM, David Kiarie wrote:
> >Add IVRS table for AMD IO MMU.
> >
> >Signed-off-by: David Kiarie 
> >---
> >  hw/i386/acpi-build.c| 70 
> > +
> >  include/hw/acpi/acpi-defs.h | 55 +++
> >  2 files changed, 125 insertions(+)
> >
> >diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> >index 78758e2..5c0d6b7 100644
> >--- a/hw/i386/acpi-build.c
> >+++ b/hw/i386/acpi-build.c
> >@@ -52,6 +52,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"
> >@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
> >  }
> >
> >  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, &iommu_ambig);
> >+
> >+/* IVDB definition */
> >+iommu = acpi_data_push(table_data, sizeof(*iommu));
> >+if (!iommu_ambig) {
> 
> Hi,
> 
> If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
> I think we should report the error to user, something like error_report.
> 
> >+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
> >+ *  create entries for devices to be treated specially by IO MMU,
> >+ *  currently we report all devices to IO MMU with no special flags
> >+ *  DTE settings made here apply to all devices
> >+ *  Refer to AMD IOMMU spec Table 97
> >+ */
> >+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 bool acpi_has_amd_iommu(void)
> >+{
> >+bool ambiguous;
> >+Object *amd_iommu;
> >+
> >+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
> >+ &ambiguous);
> >+return amd_iommu && !ambiguous;
> >+}
> >+
> >+static void
> >  build_dsdt(GArray *table_data, GArray *linker,
> > AcpiPmInfo *pm, AcpiMiscInfo *misc)
> >  {
> >@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, 
> >AcpiBuildTables *tables)
> >  build_dmar_q35(tables_blob, tables->linker);
> >  }
> >
> >+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {
> 
> Since we have the acpi_has_amd_iommu function now, maybe is time to rename
> acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu 
> that
> returns an enum type (NONE/INTEL/AMD).
> 
> By the way, do we really need to check !acpi_has_iommu() if there is
> an AMD IOMMU in the system? Having both in the same system is a not (yet) 
> supported configuration,
> right?
> 
> Thanks,
> Marcel
> 

Long term the right thing to do is to add description
for each IOMMU present in the system.
For example, we might have multiple intel iommus.

> >+acpi_add_table(table_offsets, tables_blob);
> >+build_amd_iommu(tables_blob, tables->linker);
> >+}
> >+
> >  if (acpi_has_nvdimm()) {
> >  nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
> >  }
> >diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> >index c7a03d4..a161358 100644
> >--- a/include/hw/acpi/acpi-defs.h
> >+++

Re: [Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-02-14 Thread Marcel Apfelbaum

On 01/18/2016 05:25 PM, David Kiarie wrote:

Add IVRS table for AMD IO MMU.

Signed-off-by: David Kiarie 
---
  hw/i386/acpi-build.c| 70 +
  include/hw/acpi/acpi-defs.h | 55 +++
  2 files changed, 125 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 78758e2..5c0d6b7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -52,6 +52,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"
@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
  }

  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, &iommu_ambig);
+
+/* IVDB definition */
+iommu = acpi_data_push(table_data, sizeof(*iommu));
+if (!iommu_ambig) {


Hi,

If the reference to AMD IOMMU is ambiguous and the table is not added to ACPI
I think we should report the error to user, something like error_report.


+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
+ *  create entries for devices to be treated specially by IO MMU,
+ *  currently we report all devices to IO MMU with no special flags
+ *  DTE settings made here apply to all devices
+ *  Refer to AMD IOMMU spec Table 97
+ */
+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 bool acpi_has_amd_iommu(void)
+{
+bool ambiguous;
+Object *amd_iommu;
+
+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
+ &ambiguous);
+return amd_iommu && !ambiguous;
+}
+
+static void
  build_dsdt(GArray *table_data, GArray *linker,
 AcpiPmInfo *pm, AcpiMiscInfo *misc)
  {
@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
  build_dmar_q35(tables_blob, tables->linker);
  }

+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {


Since we have the acpi_has_amd_iommu function now, maybe is time to rename
acpi_has_iommu to acpi_has_intel_iommu or better have a standard has_iommu that
returns an enum type (NONE/INTEL/AMD).

By the way, do we really need to check !acpi_has_iommu() if there is
an AMD IOMMU in the system? Having both in the same system is a not (yet) 
supported configuration,
right?

Thanks,
Marcel



+acpi_add_table(table_offsets, tables_blob);
+build_amd_iommu(tables_blob, tables->linker);
+}
+
  if (acpi_has_nvdimm()) {
  nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
  }
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c7a03d4..a161358 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -570,4 +570,59 @@ typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
  /* Masks for Flags field above */
  #define ACPI_DMAR_INCLUDE_PCI_ALL   1

+/* IVRS constants */
+#define ACPI_IOMMU_HARDWAREUNIT_TYPE 0x10
+#define ACPI_IOMMU_IVRS_TYPE 0x1
+#define AMD_IOMMU_HOST_ADDRESS_WIDTH 39UL
+
+/* AMD IOMMU IVRS table */
+struct AcpiAMDIOMMUIVRS {
+ACPI_TABLE_HEADER_DEF
+uint32_t v_common_info; /* common virtualization information */
+uint64_t reserved;  /* reserved  */
+} QEMU_PACKED;
+typedef struct 

[Qemu-devel] [V4 3/4] hw/i386: ACPI table for AMD IO MMU

2016-01-18 Thread David Kiarie
Add IVRS table for AMD IO MMU.

Signed-off-by: David Kiarie 
---
 hw/i386/acpi-build.c| 70 +
 include/hw/acpi/acpi-defs.h | 55 +++
 2 files changed, 125 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 78758e2..5c0d6b7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -52,6 +52,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"
@@ -2424,6 +2425,70 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 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, &iommu_ambig);
+
+/* IVDB definition */
+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
+ *  create entries for devices to be treated specially by IO MMU,
+ *  currently we report all devices to IO MMU with no special flags
+ *  DTE settings made here apply to all devices
+ *  Refer to AMD IOMMU spec Table 97
+ */
+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 bool acpi_has_amd_iommu(void)
+{
+bool ambiguous;
+Object *amd_iommu;
+
+amd_iommu = object_resolve_path_type("", TYPE_AMD_IOMMU_DEVICE,
+ &ambiguous);
+return amd_iommu && !ambiguous;
+}
+
+static void
 build_dsdt(GArray *table_data, GArray *linker,
AcpiPmInfo *pm, AcpiMiscInfo *misc)
 {
@@ -2691,6 +2756,11 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
 build_dmar_q35(tables_blob, tables->linker);
 }
 
+if (acpi_has_amd_iommu() && !acpi_has_iommu()) {
+acpi_add_table(table_offsets, tables_blob);
+build_amd_iommu(tables_blob, tables->linker);
+}
+
 if (acpi_has_nvdimm()) {
 nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
 }
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c7a03d4..a161358 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -570,4 +570,59 @@ typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
 /* Masks for Flags field above */
 #define ACPI_DMAR_INCLUDE_PCI_ALL   1
 
+/* IVRS constants */
+#define ACPI_IOMMU_HARDWAREUNIT_TYPE 0x10
+#define ACPI_IOMMU_IVRS_TYPE 0x1
+#define AMD_IOMMU_HOST_ADDRESS_WIDTH 39UL
+
+/* AMD IOMMU IVRS table */
+struct AcpiAMDIOMMUIVRS {
+ACPI_TABLE_HEADER_DEF
+uint32_t v_common_info; /* common virtualization information */
+uint64_t reserved;  /* reserved  */
+} QEMU_PACKED;
+typedef struct AcpiAMDIOMMUIVRS AcpiAMDIOMMUIVRS;
+
+/* flags in the IVHD headers */
+#define IVHD_HT_TUNEN(1UL << 0)
+#define IVHD_PASS_PW (1UL << 1)
+#define IVHD_RESPASS_PW  (1UL << 2)
+#define IVHD_ISOC(1UL << 3)
+#define IVHD_IOTLBSUP(1UL << 4)
+#define IVHD_COHERENT(1UL << 5)
+#define IVHD_PREFSUP (1UL << 6)
+#define IVHD_PPRSUP  (1UL << 7)
+
+/* features in the IVHD headers */
+#define IVHD_EFR_HATS   48
+#define IVHD_EFR_GATS   48
+#define IVHD_EFR_MSI_NUM
+#define IVHD_EFR_PNBANKS
+#define IVHD_EFR_PNCOUNTERS
+#define IVHD_EFR_PASMAX
+#define IVHD_EFR_HESUP  (1UL << 7)
+#de