[Qemu-devel] [PATCH 2/4] hw/pci-host: Add AMD IOMMU to PIIX and Q35 pcs

2015-10-08 Thread David Kiarie
From: David 

Emulate AMD IOMMU on PIIX and Q35 controlled by a command line
switch

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c | 10 ++
 hw/pci-host/q35.c  | 10 ++
 2 files changed, 20 insertions(+)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 1fb71c8..a4b07d2 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -31,6 +31,7 @@
 #include "qemu/range.h"
 #include "hw/xen/xen.h"
 #include "hw/pci-host/pam.h"
+#include "hw/i386/amd_iommu.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
@@ -290,12 +291,21 @@ static void i440fx_pcihost_realize(DeviceState *dev, 
Error **errp)
 {
 PCIHostState *s = PCI_HOST_BRIDGE(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
 
 sysbus_add_io(sbd, 0xcf8, &s->conf_mem);
 sysbus_init_ioports(sbd, 0xcf8, 4);
 
 sysbus_add_io(sbd, 0xcfc, &s->data_mem);
 sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if(machine_amd_iommu(current_machine)){
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 static void i440fx_realize(PCIDevice *dev, Error **errp)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index bd74094..cef84ff 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -470,6 +471,8 @@ static void mch_realize(PCIDevice *d, Error **errp)
 {
 int i;
 MCHPCIState *mch = MCH_PCI_DEVICE(d);
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
 
 /* setup pci memory mapping */
 pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory,
@@ -528,6 +531,13 @@ static void mch_realize(PCIDevice *d, Error **errp)
 if (machine_iommu(current_machine)) {
 mch_init_dmar(mch);
 }
+/* AMD IOMMU (AMD-Vi) */
+if (machine_amd_iommu(current_machine)){
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 uint64_t mch_mcfg_base(void)
-- 
2.1.4




[Qemu-devel] [PATCH 4/4] hw/acpi: ACPI table for AMD IOMMU

2015-10-08 Thread David Kiarie
From: David 

Add AMD IOMMU IVRS table to ACPI tables

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

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..1016ed9 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -50,6 +50,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/i386/q35-acpi-dsdt.hex"
 #include "hw/i386/acpi-dsdt.hex"
@@ -1576,10 +1577,80 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 static void
+amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
+{
+uint64_t newvalue = *value | flag;
+*(uint64_t*)value = newvalue;
+}
+
+static void
+amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
+{
+uint64_t newvalue = *value | feature;
+*value = newvalue;
+}
+
+static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+int iommu_start = table_data->len;
+bool iommu_ambig;
+uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
+
+AcpiAMDIOMMUIVRS *ivrs;
+AcpiAMDIOMMUHardwareUnit *iommu;
+
+/* IVRS definition */
+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
+ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
+ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
+ivrs->v_common_info = host_width;
+
+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 = 0x10;
+/* IVHD flags */
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
+
+iommu->length = sizeof(*iommu);
+iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
+iommu->capability_offset = s->capab_offset;
+iommu->mmio_base = s->mmio.addr;
+iommu->pci_segment = cpu_to_le16(0);
+iommu->interrupt_info = cpu_to_le16(0);
+
+/* EFR features */
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
+
+/* device entries */
+memset(iommu->dev_entries, 0, 20);
+
+/* Add device flags here */
+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);
+}
+
+static void
 build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
 {
 AcpiTableHeader *dsdt;
 
+
 assert(misc->dsdt_code && misc->dsdt_size);
 
 dsdt = acpi_data_push(table_data, misc->dsdt_size);
@@ -1658,6 +1729,16 @@ static bool acpi_has_iommu(void)
 return intel_iommu && !ambiguous;
 }
 
+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 acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 {
@@ -1741,6 +1822,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
 acpi_add_table(table_offsets, tables_blob);
 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);
+}
 
 /* Add tables supplied by user (if any) */
 for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 2b431e6..4fc1f79 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -561,4 +561,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

[Qemu-devel] [PATCH 1/4] hw/core: Add iommu to machine properties

2015-10-08 Thread David Kiarie
From: David 

 Add iommu to machine properties in preparation of introducing
 AMD IOMMU

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 25 +
 include/hw/boards.h |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 51ed6b2..8cc7461 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -269,6 +269,20 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static bool machine_get_amd_iommu(Object *obj, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+return ms->amd_iommu;
+}
+
+static void machine_set_amd_iommu(Object *obj, bool value, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+ms->amd_iommu = value;
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -420,6 +434,12 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "iommu",
 "Set on/off to enable/disable Intel IOMMU 
(VT-d)",
 NULL);
+object_property_add_bool(obj, "amd-iommu",
+ machine_get_amd_iommu,
+ machine_set_amd_iommu, NULL);
+object_property_set_description(obj, "amd-iommu",
+"Set on/off to enable/disable AMD-Vi",
+NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
  machine_set_suppress_vmdesc, NULL);
@@ -456,6 +476,11 @@ bool machine_iommu(MachineState *machine)
 return machine->iommu;
 }
 
+bool machine_amd_iommu(MachineState *machine)
+{
+return machine->amd_iommu;
+}
+
 bool machine_kernel_irqchip_allowed(MachineState *machine)
 {
 return machine->kernel_irqchip_allowed;
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 566a5ca..c8424f7 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -54,6 +54,7 @@ extern MachineState *current_machine;
 
 bool machine_usb(MachineState *machine);
 bool machine_iommu(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
@@ -140,6 +141,7 @@ struct MachineState {
 bool igd_gfx_passthru;
 char *firmware;
 bool iommu;
+bool amd_iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
-- 
2.1.4




[Qemu-devel] [PATCH 3/4] hw/i386: Introduce AMD IOMMU

2015-10-08 Thread David Kiarie
From: David 

Introduce basic AMD IOMMU emulation in Qemu. IOMMU implements event logging and
host translation which should allow nested PCI passthrough.It also implemented
a very basic IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1266 +
 hw/i386/amd_iommu.h   |  363 ++
 3 files changed, 1630 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index c250deb..85fa90f 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..092f64e
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1266 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+#define DEBUG_AMD_IOMMU
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) | 
IOMMU_DBGBIT(MMIO);
+//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) | 
IOMMU_DBGBIT(COMMAND);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+/* helper functions - FIXME - provide for reading one byte */
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+stw_le_p(&s->mmior[addr], val);
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+stl_le_p(&s->mmior[addr], val);
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
+{
+/* event logging not enabled */
+if(!s->evtlog_enabled || *(uint64_t*)&s->mmior[MMIO_STATUS] 
+   | MMIO_STATUS_EVTLOG_OF){
+return;
+}
+
+/* event log buffer full */
+if(s->evtlog_tail >= s->evtlog_len) {
+*(uint64_t*)&s->mmior[MMIO_STATUS] |= MMIO_STATUS_EVTLOG_OF;
+/* generate interrupt */
+}
+
+if(dma_memory_write(&address_space_memory, s->evtlog_len + s->evtlog_tail,
+   &evt, EVENT_LEN)){
+IOMMU_DPRINTF(ELOG, "error: fail to write at address 0x%"PRIx64
+  " + offset 0x%"PRIx32, s->evtlog, s->evtlog_tail);
+}
+
+ s->evtlog_tail += EVENT_LEN;
+ *(uint64_t*)&s->mmior[MMIO_STATUS] |= MMIO_STATUS_EVTLOG_INTR;
+}
+
+/* log an error encountered page-walking 
+ *
+ * @addr: virtual address in translation request
+ */
+static void amd_iommu_page_fault(AMDIOMMUState *s, uint16_t devid,
+ dma_addr_t addr, uint8_t info)
+{
+IOMMU_DPRINTF(ELOG, "");
+
+uint16_t evt[8];
+uint8_t status;
+
+info |= EVENT_IOPF_I;
+
+/* encode information */
+*(uint16_t*)&evt[0] = devid;
+*(uint16_t*)&evt[3] = info;
+*(uint64_t*)&evt[4] = cpu_to_be64(addr);
+
+/* log a page fault */
+amd_iommu_log_event(s, evt);
+
+/* Abort the translation */
+status = pci_get_word(s->dev.config + PCI_STATUS);
+pci_set_

[Qemu-devel] [PATCH 0/4] AMD IOMMU v1

2015-10-08 Thread David Kiarie
David (4):
  hw/core: Add iommu to machine properties
  hw/pci-host: Add AMD IOMMU to PIIX and Q35 pcs
  hw/i386: Introduce AMD IOMMU
  hw/acpi: ACPI table for AMD IOMMU

 hw/core/machine.c   |   25 +
 hw/i386/Makefile.objs   |1 +
 hw/i386/acpi-build.c|   85 +++
 hw/i386/amd_iommu.c | 1266 +++
 hw/i386/amd_iommu.h |  363 +
 hw/pci-host/piix.c  |   10 +
 hw/pci-host/q35.c   |   10 +
 include/hw/acpi/acpi-defs.h |   55 ++
 include/hw/boards.h |2 +
 9 files changed, 1817 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h


AMD IOMMU v1

Changes since RFC
-code cleanup around MMIO code
-compacted startup code - some of the 'init' and 'reset' code is similar 
and can be reused
-Implemented basic IOTLB - it's just a hashtable of already requested 
virtual address translations whereby if a device requests translation of the 
same address we don't have to do a page walk, again.
-Implemented event logging - this version logs about all possible SW/HW 
errors but most of them are very unlikely to occur.
-Changed GVA and HVA to go by the physical host bus implementations - 48 
bits virtual and 40 bits physical address space.

TODO
   -Implement MMIO reserving code
   -Implement r/wc MMIO registers
   -Implement interrupts related to r/wc registers

IOMMU won't be able to implement PPR logging with the current Qemu 
infrastructure - Qemu doesn't implement anything that's related to PASID. 
Similary, guest translation won't be possible.

Note: I have not tested this code and it might have a few bugs (silly bugs) of 
course but the RFC version works so, if present, it's just minor bugs.
-- 
2.1.4




Re: [Qemu-devel] [PATCH 0/4] AMD IOMMU v1

2015-10-09 Thread David kiarie
On Fri, Oct 9, 2015 at 10:17 AM, Valentine Sinitsyn
 wrote:
> Hi David,
>
> Thanks for your efforts.
>
>
> On 09.10.2015 07:53, David Kiarie wrote:
>>
>> David (4):
>>hw/core: Add iommu to machine properties
>>hw/pci-host: Add AMD IOMMU to PIIX and Q35 pcs
>>hw/i386: Introduce AMD IOMMU
>>hw/acpi: ACPI table for AMD IOMMU
>>
>>   hw/core/machine.c   |   25 +
>>   hw/i386/Makefile.objs   |1 +
>>   hw/i386/acpi-build.c|   85 +++
>>   hw/i386/amd_iommu.c | 1266
>> +++
>>   hw/i386/amd_iommu.h |  363 +
>>   hw/pci-host/piix.c  |   10 +
>>   hw/pci-host/q35.c   |   10 +
>>   include/hw/acpi/acpi-defs.h |   55 ++
>>   include/hw/boards.h |2 +
>>   9 files changed, 1817 insertions(+)
>>   create mode 100644 hw/i386/amd_iommu.c
>>   create mode 100644 hw/i386/amd_iommu.h
>>
>>
>> AMD IOMMU v1
>>
>> Changes since RFC
>>  -code cleanup around MMIO code
>>  -compacted startup code - some of the 'init' and 'reset' code is
>> similar and can be reused
>>  -Implemented basic IOTLB - it's just a hashtable of already requested
>> virtual address translations whereby if a device requests translation of the
>> same address we don't have to do a page walk, again.
>>  -Implemented event logging - this version logs about all possible
>> SW/HW errors but most of them are very unlikely to occur.
>>  -Changed GVA and HVA to go by the physical host bus implementations -
>> 48 bits virtual and 40 bits physical address space.
>
> I haven't looked into this closely yet, but shouldn't you support a whole 63
> bits wide addresses (and 6-level page tables),  as per specification?
>
Am not sure too.

When I tested this, linux was using 3-level pages.

I went with 48 bits as AFAIK that's what current hardware works. This
code should work with 6-levels though I just used 48 to be 'safe'.

>>
>> TODO
>> -Implement MMIO reserving code
>> -Implement r/wc MMIO registers
>> -Implement interrupts related to r/wc registers
>>
>> IOMMU won't be able to implement PPR logging with the current Qemu
>> infrastructure - Qemu doesn't implement anything that's related to PASID.
>> Similary, guest translation won't be possible.
>>
>> Note: I have not tested this code and it might have a few bugs (silly
>> bugs) of course but the RFC version works so, if present, it's just minor
>> bugs.
>
>
> Regards,
> Valentine Sinitsyn



Re: [Qemu-devel] [PATCH 0/4] AMD IOMMU v1

2015-10-09 Thread David kiarie
On Fri, Oct 9, 2015 at 3:24 PM, Valentine Sinitsyn
 wrote:
> On 09.10.2015 17:22, David kiarie wrote:
>>
>> On Fri, Oct 9, 2015 at 10:17 AM, Valentine Sinitsyn
>>  wrote:
>>>
>>> Hi David,
>>>
>>> Thanks for your efforts.
>>>
>>>
>>> On 09.10.2015 07:53, David Kiarie wrote:
>>>>
>>>>
>>>> David (4):
>>>> hw/core: Add iommu to machine properties
>>>> hw/pci-host: Add AMD IOMMU to PIIX and Q35 pcs
>>>> hw/i386: Introduce AMD IOMMU
>>>> hw/acpi: ACPI table for AMD IOMMU
>>>>
>>>>hw/core/machine.c   |   25 +
>>>>hw/i386/Makefile.objs   |1 +
>>>>hw/i386/acpi-build.c|   85 +++
>>>>hw/i386/amd_iommu.c | 1266
>>>> +++
>>>>hw/i386/amd_iommu.h |  363 +
>>>>hw/pci-host/piix.c  |   10 +
>>>>hw/pci-host/q35.c   |   10 +
>>>>include/hw/acpi/acpi-defs.h |   55 ++
>>>>include/hw/boards.h |2 +
>>>>9 files changed, 1817 insertions(+)
>>>>create mode 100644 hw/i386/amd_iommu.c
>>>>create mode 100644 hw/i386/amd_iommu.h
>>>>
>>>>
>>>> AMD IOMMU v1
>>>>
>>>> Changes since RFC
>>>>   -code cleanup around MMIO code
>>>>   -compacted startup code - some of the 'init' and 'reset' code is
>>>> similar and can be reused
>>>>   -Implemented basic IOTLB - it's just a hashtable of already
>>>> requested
>>>> virtual address translations whereby if a device requests translation of
>>>> the
>>>> same address we don't have to do a page walk, again.
>>>>   -Implemented event logging - this version logs about all possible
>>>> SW/HW errors but most of them are very unlikely to occur.
>>>>   -Changed GVA and HVA to go by the physical host bus
>>>> implementations -
>>>> 48 bits virtual and 40 bits physical address space.
>>>
>>>
>>> I haven't looked into this closely yet, but shouldn't you support a whole
>>> 63
>>> bits wide addresses (and 6-level page tables),  as per specification?
>>>
>> Am not sure too.
>>
>> When I tested this, linux was using 3-level pages.
>
> Nobody uses whole 6 page table levels, to the best of my knowledge.
> Supporting (emulating) them, however, is part of the spec. Besides, it will
> be needed if one decides to share page tables between IOMMU and CPU
>

Should I use 6 levels/64 bit virtual address space ?

>>
>> I went with 48 bits as AFAIK that's what current hardware works. This
>> code should work with 6-levels though I just used 48 to be 'safe'.
>>
>>>>
>>>> TODO
>>>>  -Implement MMIO reserving code
>>>>  -Implement r/wc MMIO registers
>>>>  -Implement interrupts related to r/wc registers
>>>>
>>>> IOMMU won't be able to implement PPR logging with the current Qemu
>>>> infrastructure - Qemu doesn't implement anything that's related to
>>>> PASID.
>>>> Similary, guest translation won't be possible.
>>>>
>>>> Note: I have not tested this code and it might have a few bugs (silly
>>>> bugs) of course but the RFC version works so, if present, it's just
>>>> minor
>>>> bugs.
>>>
>>>
>>>
>>> Regards,
>>> Valentine Sinitsyn
>
>
> Regards,
> Valentine Sinitsyn



Re: [Qemu-devel] [PATCH 3/4] hw/i386: Introduce AMD IOMMU

2015-10-09 Thread David kiarie
On Thu, Oct 8, 2015 at 9:24 PM, Marcel Apfelbaum
 wrote:
> On 10/09/2015 05:53 AM, David Kiarie wrote:
>>
>> From: David 
>>
>> Introduce basic AMD IOMMU emulation in Qemu. IOMMU implements event
>> logging and
>> host translation which should allow nested PCI passthrough.It also
>> implemented
>> a very basic IOTLB implementation
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/i386/Makefile.objs |1 +
>>   hw/i386/amd_iommu.c   | 1266
>> +
>>   hw/i386/amd_iommu.h   |  363 ++
>>   3 files changed, 1630 insertions(+)
>>   create mode 100644 hw/i386/amd_iommu.c
>>   create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index c250deb..85fa90f 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>   obj-y += pc.o pc_piix.o pc_q35.o
>>   obj-y += pc_sysfw.o
>>   obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>   obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..092f64e
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1266 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) |
>> IOMMU_DBGBIT(MMIO);
>> +//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) |
>> IOMMU_DBGBIT(COMMAND);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* helper functions - FIXME - provide for reading one byte */
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +stw_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
>> +{
>> +stl_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
>> +{
>> +/* event logging not enabled */
>> +if(!s->evtlog_enabled || *(uint64_t*)&s->mmior[MMIO_STATUS]
>> +   | MMIO_STATUS_EVTLOG_OF){
>> +return;
>> +}
>> +
>> +/* event log buffer full */
>> +if(s->evtlog_tail >= s->ev

Re: [Qemu-devel] [PATCH 1/4] hw/core: Add iommu to machine properties

2015-10-09 Thread David kiarie
On Thu, Oct 8, 2015 at 9:10 PM, Marcel Apfelbaum
 wrote:
> On 10/09/2015 05:53 AM, David Kiarie wrote:
>>
>> From: David 
>>
>>   Add iommu to machine properties in preparation of introducing
>>   AMD IOMMU
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/core/machine.c   | 25 +
>>   include/hw/boards.h |  2 ++
>>   2 files changed, 27 insertions(+)
>>
>> diff --git a/hw/core/machine.c b/hw/core/machine.c
>> index 51ed6b2..8cc7461 100644
>> --- a/hw/core/machine.c
>> +++ b/hw/core/machine.c
>> @@ -269,6 +269,20 @@ static void machine_set_iommu(Object *obj, bool
>> value, Error **errp)
>>   ms->iommu = value;
>>   }
>>
>> +static bool machine_get_amd_iommu(Object *obj, Error **errp)
>> +{
>> +MachineState *ms = MACHINE(obj);
>> +
>> +return ms->amd_iommu;
>> +}
>> +
>> +static void machine_set_amd_iommu(Object *obj, bool value, Error **errp)
>> +{
>> +MachineState *ms = MACHINE(obj);
>> +
>> +ms->amd_iommu = value;
>> +}
>> +
>>   static void machine_set_suppress_vmdesc(Object *obj, bool value, Error
>> **errp)
>>   {
>>   MachineState *ms = MACHINE(obj);
>> @@ -420,6 +434,12 @@ static void machine_initfn(Object *obj)
>>   object_property_set_description(obj, "iommu",
>>   "Set on/off to enable/disable Intel
>> IOMMU (VT-d)",
>>   NULL);
>> +object_property_add_bool(obj, "amd-iommu",
>> + machine_get_amd_iommu,
>> + machine_set_amd_iommu, NULL);
>> +object_property_set_description(obj, "amd-iommu",
>> +"Set on/off to enable/disable
>> AMD-Vi",
>> +NULL);
>>   object_property_add_bool(obj, "suppress-vmdesc",
>>machine_get_suppress_vmdesc,
>>machine_set_suppress_vmdesc, NULL);
>> @@ -456,6 +476,11 @@ bool machine_iommu(MachineState *machine)
>>   return machine->iommu;
>>   }
>>
>> +bool machine_amd_iommu(MachineState *machine)
>> +{
>> +return machine->amd_iommu;
>> +}
>> +
>>   bool machine_kernel_irqchip_allowed(MachineState *machine)
>>   {
>>   return machine->kernel_irqchip_allowed;
>> diff --git a/include/hw/boards.h b/include/hw/boards.h
>> index 566a5ca..c8424f7 100644
>> --- a/include/hw/boards.h
>> +++ b/include/hw/boards.h
>> @@ -54,6 +54,7 @@ extern MachineState *current_machine;
>>
>>   bool machine_usb(MachineState *machine);
>>   bool machine_iommu(MachineState *machine);
>> +bool machine_amd_iommu(MachineState *machine);
>>   bool machine_kernel_irqchip_allowed(MachineState *machine);
>>   bool machine_kernel_irqchip_required(MachineState *machine);
>>   int machine_kvm_shadow_mem(MachineState *machine);
>> @@ -140,6 +141,7 @@ struct MachineState {
>>   bool igd_gfx_passthru;
>>   char *firmware;
>>   bool iommu;
>> +bool amd_iommu;
>>   bool suppress_vmdesc;
>>
>>   ram_addr_t ram_size;
>>
>
> Hi,
>
> I think we should add the property to PC_MACHINE class because it make sense
> only
> for PC and Q35 machines (right?).

Right.

> MACHINE is the base class for all the architectures.
>
> On the same note, "iommu" refers to intel_iommu and maybe we should
> move it also to the PC_MACHINE.
> I understand that it is not in the scope of your series, we can add a patch
> later.
>
> Another possibility would be to keep the same "iommu" property, but change
> it from boolean
> to off|intel|amd|... . This will break backward compatibility, on the other
> hand having
> iommu referring to Intel only when we have  multiple iommu implementations
> is ugly IMHO.
>

Okay. I think I could look into the last option.

> Thanks,
> Marcel
>
>



Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>> The IO MMU does basic translation, error checking and has a
>> minimal IOTLB implementation.
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/Makefile.objs |1 +
>>  hw/i386/amd_iommu.c   | 1409 
>> +
>>  hw/i386/amd_iommu.h   |  399 ++
>>  include/hw/pci/pci.h  |2 +
>>  4 files changed, 1811 insertions(+)
>>  create mode 100644 hw/i386/amd_iommu.c
>>  create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>  obj-y += pc.o pc_piix.o pc_q35.o
>>  obj-y += pc_sysfw.o
>>  obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>  obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..20111fe
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1409 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>
> Link to hardware spec?
>
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +stq_le_p(&s->romask[addr], romask);
>> +stq_le_p(&s->w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);
>> +}
>> +
>> +/* internal write */
>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>> addr)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +/* external write */
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +uint16_t romask = lduw_le_p(&s->romask[addr]);
>> +uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
>> +uint16_t oldval = lduw_le_p(&s->mmior[addr]);
>> +stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint

Re: [Qemu-devel] [V4 4/4] hw/pci-host: Emulate AMD IO MMU

2016-02-14 Thread David kiarie
On Sun, Feb 14, 2016 at 4:02 PM, Marcel Apfelbaum
 wrote:
> On 01/18/2016 05:25 PM, David Kiarie wrote:
>>
>> Support AMD IO MMU emulation in q35 and piix chipsets
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/pci-host/piix.c | 11 +++
>>   hw/pci-host/q35.c  | 14 --
>>   2 files changed, 23 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> index b0d7e31..3ba245d 100644
>> --- a/hw/pci-host/piix.c
>> +++ b/hw/pci-host/piix.c
>> @@ -35,6 +35,7 @@
>>   #include "hw/i386/ioapic.h"
>>   #include "qapi/visitor.h"
>>   #include "qemu/error-report.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>   /*
>>* I440FX chipset data sheet.
>> @@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState *dev,
>> Error **errp)
>>
>>   sysbus_add_io(sbd, 0xcfc, &s->data_mem);
>>   sysbus_init_ioports(sbd, 0xcfc, 4);
>> +
>> +/* AMD IOMMU (AMD-Vi) */
>> +if (g_strcmp0(object_property_get_str(qdev_get_machine(), "iommu",
>> NULL),
>> +  "amd") == 0) {
>
>
> Hi,
>
> Minor comments, here you can use the same qdev_get_machine())->iommu as used
> below
> and the same AMD_IOMMU_STR instead of "amd".
>
> Do I understand correctly that we can have an AMD IOMMU working on an i440fx
> machine (non PCI Express)?

Well, we could say, it worked - then because I didn't have any
interrupts yet but I wont work anymore since am going to add an
interrupt with event logging.

Will resend, as soon as possible.

>
> Thanks,
> Marcel
>
>
>> +AMDIOMMUState *iommu_state;
>> +PCIDevice *iommu;
>> +iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> +iommu_state = AMD_IOMMU_DEVICE(iommu);
>> +pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
>> +}
>>   }
>>
>>   static void i440fx_realize(PCIDevice *dev, Error **errp)
>> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> index 1fb4707..0c60e3c 100644
>> --- a/hw/pci-host/q35.c
>> +++ b/hw/pci-host/q35.c
>> @@ -30,6 +30,7 @@
>>   #include "hw/hw.h"
>>   #include "hw/pci-host/q35.h"
>>   #include "qapi/visitor.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>
>> /
>>* Q35 host
>> @@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>>mch->pci_address_space, &mch->pam_regions[i+1],
>>PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>>   }
>> -/* Intel IOMMU (VT-d) */
>> -if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> +
>> +if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) ==
>> 0) {
>> +/* Intel IOMMU (VT-d) */
>>   mch_init_dmar(mch);
>> +} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>> AMD_IOMMU_STR)
>> +   == 0) {
>> +AMDIOMMUState *iommu_state;
>> +PCIDevice *iommu;
>> +PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> +iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> +iommu_state = AMD_IOMMU_DEVICE(iommu);
>> +pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>>   }
>>   }
>>
>>
>



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

Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>> The IO MMU does basic translation, error checking and has a
>> minimal IOTLB implementation.
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/Makefile.objs |1 +
>>  hw/i386/amd_iommu.c   | 1409 
>> +
>>  hw/i386/amd_iommu.h   |  399 ++
>>  include/hw/pci/pci.h  |2 +
>>  4 files changed, 1811 insertions(+)
>>  create mode 100644 hw/i386/amd_iommu.c
>>  create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>  obj-y += pc.o pc_piix.o pc_q35.o
>>  obj-y += pc_sysfw.o
>>  obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>  obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..20111fe
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1409 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>
> Link to hardware spec?
>
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +stq_le_p(&s->romask[addr], romask);
>> +stq_le_p(&s->w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);
>> +}
>> +
>> +/* internal write */
>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>> addr)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +/* external write */
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +uint16_t romask = lduw_le_p(&s->romask[addr]);
>> +uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
>> +uint16_t oldval = lduw_le_p(&s->mmior[addr]);
>> +stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint

Re: [Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-14 Thread David kiarie
On Mon, Feb 15, 2016 at 6:41 AM, David kiarie  wrote:
> On Thu, Feb 4, 2016 at 6:03 PM, Michael S. Tsirkin  wrote:
>> On Mon, Jan 18, 2016 at 06:25:42PM +0300, David Kiarie wrote:
>>> Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
>>> The IO MMU does basic translation, error checking and has a
>>> minimal IOTLB implementation.
>>>
>>> Signed-off-by: David Kiarie 
>>> ---
>>>  hw/i386/Makefile.objs |1 +
>>>  hw/i386/amd_iommu.c   | 1409 
>>> +
>>>  hw/i386/amd_iommu.h   |  399 ++
>>>  include/hw/pci/pci.h  |2 +
>>>  4 files changed, 1811 insertions(+)
>>>  create mode 100644 hw/i386/amd_iommu.c
>>>  create mode 100644 hw/i386/amd_iommu.h
>>>
>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>> index b52d5b8..2f1a265 100644
>>> --- a/hw/i386/Makefile.objs
>>> +++ b/hw/i386/Makefile.objs
>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>  obj-y += pc.o pc_piix.o pc_q35.o
>>>  obj-y += pc_sysfw.o
>>>  obj-y += intel_iommu.o
>>> +obj-y += amd_iommu.o
>>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>
>>>  obj-y += kvmvapic.o
>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>> new file mode 100644
>>> index 000..20111fe
>>> --- /dev/null
>>> +++ b/hw/i386/amd_iommu.c
>>> @@ -0,0 +1,1409 @@
>>> +/*
>>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>>> + *
>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>> + * Copyright (C) 2015 David Kiarie, 
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> +
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> +
>>> + * You should have received a copy of the GNU General Public License along
>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>>
>> Link to hardware spec?
>>
>>> + *
>>> + */
>>> +#include "hw/i386/amd_iommu.h"
>>> +
>>> +//#define DEBUG_AMD_IOMMU
>>> +#ifdef DEBUG_AMD_IOMMU
>>> +enum {
>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>> +};
>>> +
>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>>> +
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>>> +## __VA_ARGS__); } \
>>> +} while (0)
>>> +#else
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>>> +#endif
>>> +
>>> +/* configure MMIO registers at startup/reset */
>>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>>> +   uint64_t romask, uint64_t w1cmask)
>>> +{
>>> +stq_le_p(&s->mmior[addr], val);
>>> +stq_le_p(&s->romask[addr], romask);
>>> +stq_le_p(&s->w1cmask[addr], w1cmask);
>>> +}
>>> +
>>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return lduw_le_p(&s->mmior[addr]);
>>> +}
>>> +
>>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return ldl_le_p(&s->mmior[addr]);
>>> +}
>>> +
>>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>>> +{
>>> +return ldq_le_p(&s->mmior[addr]);
>>> +}
>>> +
>>> +/* internal write */
>>> +static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr 
>>> addr)
>>> +{
>>> +stq_le_p(&s->mmior[addr], val);
>>> +}
>>> +
>>> +/*

[Qemu-devel] [V4 2/4] hw/core: Add AMD IO MMU to machine properties

2016-02-17 Thread David Kiarie
Add IO MMU as a string to machine properties which
is used to control whether and they type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 28 
 include/hw/boards.h |  3 ++-
 qemu-options.hx |  6 +++---
 util/qemu-config.c  |  4 ++--
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 1261368..6379f24 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -14,6 +14,8 @@
 #include "hw/boards.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -284,18 +286,28 @@ static void machine_set_firmware(Object *obj, const char 
*value, Error **errp)
 ms->firmware = g_strdup(value);
 }
 
-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-return ms->iommu;
+return g_strdup(ms->iommu);
 }
 
-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
+Error *err = NULL;
+
+g_free(ms->iommu);
+
+if (g_strcmp0(value, AMD_IOMMU_STR) &&
+g_strcmp0(value, INTEL_IOMMU_STR)) {
+error_setg(errp, "Invalid IO MMU type %s", value);
+error_propagate(errp, err);
+return;
+}
 
-ms->iommu = value;
+ms->iommu = g_strdup(value);
 }
 
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
@@ -455,11 +467,10 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "firmware",
 "Firmware image",
 NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"IOMMU list",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
@@ -485,6 +496,7 @@ static void machine_finalize(Object *obj)
 g_free(ms->dumpdtb);
 g_free(ms->dt_compatible);
 g_free(ms->firmware);
+g_free(ms->iommu);
 }
 
 bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
 int machine_phandle_start(MachineState *machine);
 bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
 bool usb_disabled;
 bool igd_gfx_passthru;
 char *firmware;
-bool iommu;
+char *iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index 733a194..9ac92c1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=amd|intel enables and selects the emulated IO MMU 
(default: off)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -72,8 +72,8 @@ Include guest memory in a core dump. The default is on.
 Enables or disables memory merge support. This feature, when supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
-@item iomm

[Qemu-devel] [V4 0/4] AMD IOMMU

2016-02-17 Thread David Kiarie
Hello there,

This is v5 of AMD IOMMU patches that fixes the issues mentioned in v4 except I 
fail to see the endian-ness issues Michael mentioned.

I also stripped PIIX AMD IOMMU support since I added an MSI interrupt. One of 
the patches has a conflict with current master but it this is mergable I could 
quickly send a clean patch.

Thanks!

David Kiarie (4):
  hw/i386: Introduce AMD IO MMU
  hw/core: Add AMD IO MMU to machine properties
  hw/i386: ACPI table for AMD IO MMU
  hw/pci-host: Emulate AMD IO MMU

 hw/core/machine.c |   28 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |   98 ++-
 hw/i386/amd_iommu.c   | 1430 +
 hw/i386/amd_iommu.h   |  395 
 hw/pci-host/piix.c|1 +
 hw/pci-host/q35.c |   14 +-
 include/hw/acpi/acpi-defs.h   |   55 ++
 include/hw/boards.h   |3 +-
 include/hw/i386/intel_iommu.h |1 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |6 +-
 util/qemu-config.c|4 +-
 13 files changed, 2011 insertions(+), 27 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-02-17 Thread David Kiarie
Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
The IO MMU does basic translation, error checking and has a
minimal IOTLB implementation.

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1430 +
 hw/i386/amd_iommu.h   |  395 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1828 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..b3b977f
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1430 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+uint64_t romask = ldq_le_p(&s->romask[addr]);
+uint64_t w1cmask = ldq_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldq_le_p(&s->mmior[addr]);
+stq_l

[Qemu-devel] [V4 4/4] hw/pci-host: Emulate AMD IO MMU

2016-02-17 Thread David Kiarie
Add AMD IO MMU emulation support to q35 chipset

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c|  1 +
 hw/pci-host/q35.c | 14 --
 include/hw/i386/intel_iommu.h |  1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 3832ed6..6aad34c 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -36,6 +36,7 @@
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"
 
 /*
  * I440FX chipset data sheet.
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 42b421e..7284bdd 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -506,9 +507,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) == 0) {
+/* Intel IOMMU (VT-d) */
 mch_init_dmar(mch);
+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, AMD_IOMMU_STR)
+   == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
 }
 }
 
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 5dbadb7..0b32bd6 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -27,6 +27,7 @@
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
-- 
2.1.4




[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) {

[Qemu-devel] [V3 0/4] AMD IOMMU

2016-01-14 Thread David Kiarie
David Kiarie (4):
  hw/core: Add AMD IO MMU to machine properties
  hw/i386: ACPI table for AMD IO MMU
  hw/pci-host: Emulate AMD IO MMU

 hw/core/machine.c   |   17 +-
 hw/i386/Makefile.objs   |1 +
 hw/i386/acpi-build.c|   96 +++
 hw/i386/amd_iommu.c | 1420 +++
 hw/i386/amd_iommu.h |  399 
 hw/pci-host/piix.c  |   11 +
 hw/pci-host/q35.c   |   16 +-
 include/hw/acpi/acpi-defs.h |   55 ++
 include/hw/boards.h |3 +-
 include/hw/pci/pci.h|2 +
 qemu-options.hx |6 +-
 util/qemu-config.c  |4 +-
 12 files changed, 2014 insertions(+), 16 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

Hello,

This series introduces AMD IO MMU emulation to qemu. It's the third version.

Changes since v2.
  -Coding style; fixed all errors reported by scripts/checkpatch.pl as 
suggested by Micheal
  -Implemented read/only and write 1/clear registers to IO MMU MMIO 
  -Cleaned up dead code
  -Introduced a switch that controls IO MMU emulation and what type is emulated 
i.e 
q35,iommu=amd|intel
   as suggested by Marcel
  -Tested with audio device passthrough (ac97 with sound driver alsa)
  -Reserved memory for IO MMU MMIO via ACPI (I need someone to check this)

I was supposed to implement interrupts related to w1/c registers but I decided 
to reserve everything to do with interrupts for later

Testing procedure outlined here 
   http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
-- 
2.1.4




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

2016-01-14 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| 96 +
 include/hw/acpi/acpi-defs.h | 55 ++
 2 files changed, 151 insertions(+)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 78758e2..5a5d594 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,88 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 static void
+amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
+{
+uint64_t newvalue = *value | flag;
+*(uint64_t *)value = newvalue;
+}
+
+static void
+amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
+{
+uint64_t newvalue = *value | feature;
+*value = newvalue;
+}
+
+static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+int iommu_start = table_data->len;
+bool iommu_ambig;
+uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
+
+AcpiAMDIOMMUIVRS *ivrs;
+AcpiAMDIOMMUHardwareUnit *iommu;
+
+/* IVRS definition */
+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
+ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
+ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
+ivrs->v_common_info = host_width;
+
+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 = 0x10;
+/* IVHD flags */
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
+
+iommu->length = sizeof(*iommu);
+iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
+iommu->capability_offset = s->capab_offset;
+iommu->mmio_base = s->mmio.addr;
+fprintf(stderr, "MMIO addr acpi %lx",  s->mmio.addr);
+
+iommu->pci_segment = cpu_to_le16(0);
+iommu->interrupt_info = cpu_to_le16(0);
+
+/* EFR features */
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
+
+/* device entries */
+memset(iommu->dev_entries, 0, 20);
+
+/* Add device flags here */
+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)
 {
@@ -2481,6 +2564,14 @@ build_dsdt(GArray *table_data, GArray *linker,
 build_q35_pci0_int(dsdt);
 }
 
+/* AMD IOMMU */
+if (acpi_has_amd_iommu()) {
+sb_scope = aml_scope("_SB");
+aml_append(sb_scope,
+aml_operation_region("AMDV", AML_SYSTEM_MEMORY, IOMMU_BASE_ADDR,
+ 16*1024));
+}
+
 build_cpu_hotplug_aml(dsdt);
 build_memory_hotplug_aml(dsdt, nr_mem, pm->mem_hp_io_base,
  pm->mem_hp_io_len);
@@ -2691,6 +2782,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 AcpiDmarHa

[Qemu-devel] [V3 2/4] hw/core: Add AMD IO MMU to machine properties

2016-01-14 Thread David Kiarie
Add IO MMU as a string to machine properties which
is used to control whether and they type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 17 +
 include/hw/boards.h |  3 ++-
 qemu-options.hx |  6 +++---
 util/qemu-config.c  |  4 ++--
 4 files changed, 16 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c46ddc7..cb309aa 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -283,18 +283,19 @@ static void machine_set_firmware(Object *obj, const char 
*value, Error **errp)
 ms->firmware = g_strdup(value);
 }
 
-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-return ms->iommu;
+return g_strdup(ms->iommu);
 }
 
-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-ms->iommu = value;
+g_free(ms->iommu);
+ms->iommu = g_strdup(value);
 }
 
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
@@ -454,11 +455,10 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "firmware",
 "Firmware image",
 NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"IOMMU list",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
@@ -484,6 +484,7 @@ static void machine_finalize(Object *obj)
 g_free(ms->dumpdtb);
 g_free(ms->dt_compatible);
 g_free(ms->firmware);
+g_free(ms->iommu);
 }
 
 bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
 int machine_phandle_start(MachineState *machine);
 bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
 bool usb_disabled;
 bool igd_gfx_passthru;
 char *firmware;
-bool iommu;
+char *iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index 215d00d..ac327c8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=amd|intel enables and selects the emulated IO MMU 
(default: off)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -72,8 +72,8 @@ Include guest memory in a core dump. The default is on.
 Enables or disables memory merge support. This feature, when supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
-@item iommu=on|off
-Enables or disables emulated Intel IOMMU (VT-d) support. The default is off.
+@item iommu=intel|amd
+Enables and selects the emulated IO MMU. The default is off.
 @item aes-key-wrap=on|off
 Enables or disables AES key wrapping support on s390-ccw hosts. This feature
 controls whether AES wrapping keys will be created to allow
diff --git a/util/qemu-config.c b/util/qemu-config.c
index 687fd34..f79b98c 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -213,8 +213,8 @@ static QemuOptsList machine_opts = {
 .help = "firmware image",
 },{

[Qemu-devel] [V3 4/4] hw/pci-host: Emulate AMD IO MMU

2016-01-14 Thread David Kiarie
Support AMD IO MMU emulation in q35 and piix chipsets

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c | 11 +++
 hw/pci-host/q35.c  | 16 ++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 924f0fa..19e2930 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -35,6 +35,7 @@
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"
 
 /*
  * I440FX chipset data sheet.
@@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_add_io(sbd, 0xcfc, &s->data_mem);
 sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if (g_strcmp0(object_property_get_str(qdev_get_machine(), "iommu", NULL),
+  "amd") == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 static void i440fx_realize(PCIDevice *dev, Error **errp)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 1fb4707..dd4c822 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -505,10 +506,21 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+char *iommu = object_property_get_str(qdev_get_machine(), "iommu", NULL);
+
+if (g_strcmp0(iommu, "intel") == 0) {
+/* Intel IOMMU (VT-d) */
 mch_init_dmar(mch);
+} else if (g_strcmp0(iommu, "amd") == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
 }
+g_free(iommu);
 }
 
 uint64_t mch_mcfg_base(void)
-- 
2.1.4




[Qemu-devel] [V3 1/4] hw/i386: Introduce AMD IO MMU

2016-01-14 Thread David Kiarie
From: David 

Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
The IO MMU does basic translation, error checking and has a
minimal IOTLB implementation.

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1420 +
 hw/i386/amd_iommu.h   |  399 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1822 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..4226abc
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1420 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "qemu/typedefs.h"
+#include "hw/i386/amd_iommu.h"
+
+#define DEBUG_AMD_IOMMU
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+uint64_t romask = ldq_le_p(&s->romask[addr]);
+uint64_t w1cmask = ldq_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldq_le_p(&s->mmior[addr]);
+stq_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
+{
+/* event logging not enabled */
+if (!s->evtlog_enabled || *(uint64_t *)&s->mmior[MMIO_STATUS]
+   | MMIO_STATUS_EVT_OVF) {
+return;
+}
+
+/* event log buffer full */
+if (s->evtlog_tail >= s->evtlog_len) {
+*(uint64_t *)&s->mmior[MMIO_STATUS] |= MMIO_STATUS_EVT_OVF;
+/* generate interrupt */
+}
+
+if (dma_memory_write(&address_space_memory, s->evtlog_len 

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

2016-01-14 Thread David kiarie
On Thu, Jan 14, 2016 at 1:09 PM, Michael S. Tsirkin  wrote:
> On Thu, Jan 14, 2016 at 11:04:27AM +0300, David Kiarie wrote:
>> Add IVRS table for AMD IO MMU. Also reverve MMIO
>
> reserve?

Yeah, typo.

>
>> region for IO MMU via ACPI
>
>
> It does not look like you reserve anything.
>
> Pls add a link to hardware spec (in
> the device implementation) so we can check
> what does real hardware do.
>
> If this is it:
> http://developer.amd.com/wordpress/media/2012/10/488821.pdf
>
> then the way that works seems to be by guest
> programming the MMIO base.
> We should do the same: patch seabios and EFI to do this.

Yes, that's the spec.

We thought this could be possible via ACPI (without patching BIOS ), no ?

>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/acpi-build.c| 96 
>> +
>>  include/hw/acpi/acpi-defs.h | 55 ++
>>  2 files changed, 151 insertions(+)
>>
>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> index 78758e2..5a5d594 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,88 @@ build_dmar_q35(GArray *table_data, GArray *linker)
>>  }
>>
>>  static void
>> +amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
>> +{
>> +uint64_t newvalue = *value | flag;
>> +*(uint64_t *)value = newvalue;
>> +}
>> +
>> +static void
>> +amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
>> +{
>> +uint64_t newvalue = *value | feature;
>> +*value = newvalue;
>> +}
>> +
>
> These wrappers aren't very useful I think.
>
>> +static void
>> +build_amd_iommu(GArray *table_data, GArray *linker)
>> +{
>> +int iommu_start = table_data->len;
>> +bool iommu_ambig;
>> +uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
>> +
>> +AcpiAMDIOMMUIVRS *ivrs;
>> +AcpiAMDIOMMUHardwareUnit *iommu;
>> +
>> +/* IVRS definition */
>> +ivrs = acpi_data_push(table_data, sizeof(*ivrs));
>> +ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
>> +ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
>> +ivrs->v_common_info = host_width;
>> +
>> +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 = 0x10;
>> +/* IVHD flags */
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
>> +
>> +iommu->length = sizeof(*iommu);
>> +iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
>> +iommu->capability_offset = s->capab_offset;
>> +iommu->mmio_base = s->mmio.addr;
>> +fprintf(stderr, "MMIO addr acpi %lx",  s->mmio.addr);
>> +
>> +iommu->pci_segment = cpu_to_le16(0);
>> +iommu->interrupt_info = cpu_to_le16(0);
>> +
>> +/* EFR features */
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
>> +
>> +/* device entries */
>> +memset(iommu->dev_entries, 0, 20);
>> +
>> +/* Add device flags here */
>> +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,

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

2016-01-14 Thread David kiarie
On Thu, Jan 14, 2016 at 1:09 PM, Michael S. Tsirkin  wrote:
> On Thu, Jan 14, 2016 at 11:04:27AM +0300, David Kiarie wrote:
>> Add IVRS table for AMD IO MMU. Also reverve MMIO
>
> reserve?
>
>> region for IO MMU via ACPI
>
>
> It does not look like you reserve anything.
>
> Pls add a link to hardware spec (in
> the device implementation) so we can check
> what does real hardware do.
>
> If this is it:
> http://developer.amd.com/wordpress/media/2012/10/488821.pdf
>
> then the way that works seems to be by guest
> programming the MMIO base.
> We should do the same: patch seabios and EFI to do this.
>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/acpi-build.c| 96 
>> +
>>  include/hw/acpi/acpi-defs.h | 55 ++
>>  2 files changed, 151 insertions(+)
>>
>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> index 78758e2..5a5d594 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,88 @@ build_dmar_q35(GArray *table_data, GArray *linker)
>>  }
>>
>>  static void
>> +amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
>> +{
>> +uint64_t newvalue = *value | flag;
>> +*(uint64_t *)value = newvalue;
>> +}
>> +
>> +static void
>> +amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
>> +{
>> +uint64_t newvalue = *value | feature;
>> +*value = newvalue;
>> +}
>> +
>
> These wrappers aren't very useful I think.
>
>> +static void
>> +build_amd_iommu(GArray *table_data, GArray *linker)
>> +{
>> +int iommu_start = table_data->len;
>> +bool iommu_ambig;
>> +uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
>> +
>> +AcpiAMDIOMMUIVRS *ivrs;
>> +AcpiAMDIOMMUHardwareUnit *iommu;
>> +
>> +/* IVRS definition */
>> +ivrs = acpi_data_push(table_data, sizeof(*ivrs));
>> +ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
>> +ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
>> +ivrs->v_common_info = host_width;
>> +
>> +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 = 0x10;
>> +/* IVHD flags */
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
>> +amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
>> +
>> +iommu->length = sizeof(*iommu);
>> +iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
>> +iommu->capability_offset = s->capab_offset;
>> +iommu->mmio_base = s->mmio.addr;
>> +fprintf(stderr, "MMIO addr acpi %lx",  s->mmio.addr);
>> +
>> +iommu->pci_segment = cpu_to_le16(0);
>> +iommu->interrupt_info = cpu_to_le16(0);
>> +
>> +/* EFR features */
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
>> +amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
>> +
>> +/* device entries */
>> +memset(iommu->dev_entries, 0, 20);
>> +
>> +/* Add device flags here */
>> +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 

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

2016-01-14 Thread David kiarie
On Thu, Jan 14, 2016 at 6:42 PM, Jan Kiszka  wrote:
> On 2016-01-14 16:39, Michael S. Tsirkin wrote:
>> On Thu, Jan 14, 2016 at 03:15:38PM +0300, David kiarie wrote:
>>> On Thu, Jan 14, 2016 at 1:09 PM, Michael S. Tsirkin  wrote:
>>>> On Thu, Jan 14, 2016 at 11:04:27AM +0300, David Kiarie wrote:
>>>>> Add IVRS table for AMD IO MMU. Also reverve MMIO
>>>>
>>>> reserve?
>>>
>>> Yeah, typo.
>>>
>>>>
>>>>> region for IO MMU via ACPI
>>>>
>>>>
>>>> It does not look like you reserve anything.
>>>>
>>>> Pls add a link to hardware spec (in
>>>> the device implementation) so we can check
>>>> what does real hardware do.
>>>>
>>>> If this is it:
>>>> http://developer.amd.com/wordpress/media/2012/10/488821.pdf
>>>>
>>>> then the way that works seems to be by guest
>>>> programming the MMIO base.
>>>> We should do the same: patch seabios and EFI to do this.
>>>
>>> Yes, that's the spec.
>>>
>>> We thought this could be possible via ACPI (without patching BIOS ), no ?
>>
>> I don't see how. We should do it the way it happens on real hardware.
>>
>
> Doesn't Seabios retrieve certain ACPI fragments from QEMU via a
> pv-interface by now?
>
> Anyway, the question remains where this address comes from: The BIOS,
> which then writes it into some hw config register and reports it in
> addition via ACPI or the hardware (hard-wired).

Will look at patching BIOS.

>
> Jan
>
>



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

2016-01-14 Thread David kiarie
On Thu, Jan 14, 2016 at 7:19 PM, Jan Kiszka  wrote:
> On 2016-01-14 17:09, David kiarie wrote:
>> On Thu, Jan 14, 2016 at 6:42 PM, Jan Kiszka  wrote:
>>> On 2016-01-14 16:39, Michael S. Tsirkin wrote:
>>>> On Thu, Jan 14, 2016 at 03:15:38PM +0300, David kiarie wrote:
>>>>> On Thu, Jan 14, 2016 at 1:09 PM, Michael S. Tsirkin  
>>>>> wrote:
>>>>>> On Thu, Jan 14, 2016 at 11:04:27AM +0300, David Kiarie wrote:
>>>>>>> Add IVRS table for AMD IO MMU. Also reverve MMIO
>>>>>>
>>>>>> reserve?
>>>>>
>>>>> Yeah, typo.
>>>>>
>>>>>>
>>>>>>> region for IO MMU via ACPI
>>>>>>
>>>>>>
>>>>>> It does not look like you reserve anything.
>>>>>>
>>>>>> Pls add a link to hardware spec (in
>>>>>> the device implementation) so we can check
>>>>>> what does real hardware do.
>>>>>>
>>>>>> If this is it:
>>>>>> http://developer.amd.com/wordpress/media/2012/10/488821.pdf
>>>>>>
>>>>>> then the way that works seems to be by guest
>>>>>> programming the MMIO base.
>>>>>> We should do the same: patch seabios and EFI to do this.
>>>>>
>>>>> Yes, that's the spec.
>>>>>
>>>>> We thought this could be possible via ACPI (without patching BIOS ), no ?
>>>>
>>>> I don't see how. We should do it the way it happens on real hardware.
>>>>
>>>
>>> Doesn't Seabios retrieve certain ACPI fragments from QEMU via a
>>> pv-interface by now?
>>>
>>> Anyway, the question remains where this address comes from: The BIOS,
>>> which then writes it into some hw config register and reports it in
>>> addition via ACPI or the hardware (hard-wired).
>>
>> Will look at patching BIOS.
>
> Scanning through the spec again: As the address is not hard-wired but
> configured via registers in the extended capabilities of the
> corresponding PCI functions of an IOMMU (and also enabled that way!),
> it's up to the BIOS to allocate an appropriate address for a system.

Is there a way to modify IVRS/ACPI table from seabios because the same
address is supposed to be the IVRS table otherwise I'd have to
hard-code it :/

Anyway, will check.

>
> Jan
>
>



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

2016-01-15 Thread David kiarie
Hi all,

I think, from coreboot code, the MMIO reservation is done through an
MCFG table. I can't see one in Qemu but I don't have a clue how to
extend it. There's literally nothing about MCFG online neither do I
have an org that's a member of pcisig.

Could someone have the docs describing MCFG ?

On Thu, Jan 14, 2016 at 7:54 PM, Valentine Sinitsyn
 wrote:
> Hi all,
>
> I recall I saw IVRS filling code in the coreboot for one of the boards
> supported. David, you may want to have a look there.
>
> Valentine
> (from the phone)
>
> On Jan 14, 2016 9:29 PM, "Kevin O'Connor"  wrote:
>>
>> On Thu, Jan 14, 2016 at 12:09:46PM +0200, Michael S. Tsirkin wrote:
>> > On Thu, Jan 14, 2016 at 11:04:27AM +0300, David Kiarie wrote:
>> > > Add IVRS table for AMD IO MMU. Also reverve MMIO
>> >
>> > reserve?
>> >
>> > > region for IO MMU via ACPI
>> >
>> >
>> > It does not look like you reserve anything.
>> >
>> > Pls add a link to hardware spec (in
>> > the device implementation) so we can check
>> > what does real hardware do.
>> >
>> > If this is it:
>> > http://developer.amd.com/wordpress/media/2012/10/488821.pdf
>> >
>> > then the way that works seems to be by guest
>> > programming the MMIO base.
>> > We should do the same: patch seabios and EFI to do this.
>>
>> A similar question - how does a typical factory BIOS select which
>> address to set as the MMIO base?  Is it generally hard-coded or is it
>> allocated from a range in some way?
>>
>> -Kevin



[Qemu-devel] [V4 0/4] AMD IO MMU

2016-01-18 Thread David Kiarie
David Kiarie (4):
  hw/i386: Introduce AMD IO MMU
  hw/core: Add AMD IO MMU to machine properties
  hw/i386: ACPI table for AMD IO MMU
  hw/pci-host: Emulate AMD IO MMU

 hw/core/machine.c |   17 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |   70 ++
 hw/i386/amd_iommu.c   | 1409 +
 hw/i386/amd_iommu.h   |  399 
 hw/pci-host/piix.c|   11 +
 hw/pci-host/q35.c |   14 +-
 include/hw/acpi/acpi-defs.h   |   55 ++
 include/hw/boards.h   |3 +-
 include/hw/i386/intel_iommu.h |1 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |6 +-
 util/qemu-config.c|4 +-
 vl.c  |8 +
 14 files changed, 1984 insertions(+), 16 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

Hi all, 

V4 of IO MMU patches.
Changes since V3
 -Fixed Marcel's comments
 -byte swapping in ACPI code fixed


As for IO MMU MMIO region:

This is the code that sets up the IO MMU base address in coreboot. It seems to 
be reading something from the BUS config region which as per the comment should 
have a value written by BIOS.

case CB_AmdSetMidPostConfig:
nbConfigPtr->pNbConfig->IoApicBaseAddress = 
IO_APIC_ADDR;
#ifndef IOMMU_SUPPORT_DISABLE //TODO enable iommu
/* SBIOS must alloc 16K memory for IOMMU MMIO */
UINT32  MmcfgBarAddress; //using default 
IOmmuBaseAddress
LibNbPciRead(nbConfigPtr->NbPciAddress.AddressValue | 
0x1C,
AccessWidth32,
&MmcfgBarAddress,
nbConfigPtr);
MmcfgBarAddress &= ~0xf;
if (MmcfgBarAddress != 0) {
nbConfigPtr->IommuBaseAddress = MmcfgBarAddress;
}
nbConfigPtr->IommuBaseAddress = 0; //disable iommu
#endif

I have a feeling that this is getting overly and unnecessary complex - AMD have 
their own BIOS which they, only know what it does and we have ours( which of 
course, we know how it behaves).

If we choose a static address and assign that to IO MMU mmio we could 
hypothetically have two problems.
  -SeaBIOS allocating BAR from the same region.
  -Someone selecting the region for other devices such as HPET.

The first problem can be solved as we know from what addresses seaBIOS allocats 
BARs while as for the second they should know better. I have therefore selected 
an unused IO region just next IOAPIC and HPET region and mapped 16K for IO MMU 
mmio.

David.

-- 
2.1.4




[Qemu-devel] [V4 2/4] hw/core: Add AMD IO MMU to machine properties

2016-01-18 Thread David Kiarie
Add IO MMU as a string to machine properties which
is used to control whether and the type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---
 hw/core/machine.c | 17 +
 include/hw/boards.h   |  3 ++-
 include/hw/i386/intel_iommu.h |  1 +
 qemu-options.hx   |  6 +++---
 util/qemu-config.c|  4 ++--
 vl.c  |  8 
 6 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c46ddc7..cb309aa 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -283,18 +283,19 @@ static void machine_set_firmware(Object *obj, const char 
*value, Error **errp)
 ms->firmware = g_strdup(value);
 }
 
-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-return ms->iommu;
+return g_strdup(ms->iommu);
 }
 
-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-ms->iommu = value;
+g_free(ms->iommu);
+ms->iommu = g_strdup(value);
 }
 
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
@@ -454,11 +455,10 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "firmware",
 "Firmware image",
 NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"IOMMU list",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
@@ -484,6 +484,7 @@ static void machine_finalize(Object *obj)
 g_free(ms->dumpdtb);
 g_free(ms->dt_compatible);
 g_free(ms->firmware);
+g_free(ms->iommu);
 }
 
 bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
 int machine_phandle_start(MachineState *machine);
 bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
 bool usb_disabled;
 bool igd_gfx_passthru;
 char *firmware;
-bool iommu;
+char *iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 5dbadb7..0b32bd6 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -27,6 +27,7 @@
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
diff --git a/qemu-options.hx b/qemu-options.hx
index 215d00d..ac327c8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=amd|intel enables and selects the emulated IO MMU 
(default: off)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -72,8 +72,8 @@ Include guest memory in a core dump. The default is on.
 Enables or disables memory merge support. This feature, when supported by
 the host, de-duplicates identical memory pages among VMs instances
 (ena

[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

[Qemu-devel] [V4 1/4] hw/i386: Introduce AMD IO MMU

2016-01-18 Thread David Kiarie
Add AMD IO MMU emulation to Qemu in addition to Intel IO MMU.
The IO MMU does basic translation, error checking and has a
minimal IOTLB implementation.

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1409 +
 hw/i386/amd_iommu.h   |  399 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1811 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..20111fe
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1409 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+//#define DEBUG_AMD_IOMMU
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+uint64_t romask = ldq_le_p(&s->romask[addr]);
+uint64_t w1cmask = ldq_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldq_le_p(&s->mmior[addr]);
+stq_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_log_event(AMDIOMMUState *s, uint16_t *evt)
+{
+/* event logging not enabled */
+if (!s->evtlog_enabled || *(uint64_t *)&s->mmior[MMIO_STATUS]
+   | MMIO_STATUS_EVT_OVF) {
+return;
+}
+
+/* event log buffer full */
+if (s->evtlog_tail >= s->evtlog_len) {
+*(uint64_t *)&s->mmior[MMIO_STATUS] |= MMIO_STATUS_EVT_OVF;
+/* generate interrupt */
+}
+
+if (dma_memory_write(&address_space_memory, s->evtlog_len + s->evtlog_tail,
+   

[Qemu-devel] [V4 4/4] hw/pci-host: Emulate AMD IO MMU

2016-01-18 Thread David Kiarie
Support AMD IO MMU emulation in q35 and piix chipsets

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c | 11 +++
 hw/pci-host/q35.c  | 14 --
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index b0d7e31..3ba245d 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -35,6 +35,7 @@
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"
 
 /*
  * I440FX chipset data sheet.
@@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error 
**errp)
 
 sysbus_add_io(sbd, 0xcfc, &s->data_mem);
 sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if (g_strcmp0(object_property_get_str(qdev_get_machine(), "iommu", NULL),
+  "amd") == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 static void i440fx_realize(PCIDevice *dev, Error **errp)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 1fb4707..0c60e3c 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) == 0) {
+/* Intel IOMMU (VT-d) */
 mch_init_dmar(mch);
+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, AMD_IOMMU_STR)
+   == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
 }
 }
 
-- 
2.1.4




Re: [Qemu-devel] [V3 4/4] hw/pci-host: Emulate AMD IO MMU

2016-01-18 Thread David Kiarie



On 1/17/2016 4:57 PM, Marcel Apfelbaum wrote:

On 01/14/2016 10:04 AM, David Kiarie wrote:

Support AMD IO MMU emulation in q35 and piix chipsets

Signed-off-by: David Kiarie 
---
  hw/pci-host/piix.c | 11 +++
  hw/pci-host/q35.c  | 16 ++--
  2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 924f0fa..19e2930 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -35,6 +35,7 @@
  #include "hw/i386/ioapic.h"
  #include "qapi/visitor.h"
  #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"

  /*
   * I440FX chipset data sheet.
@@ -297,6 +298,16 @@ static void i440fx_pcihost_realize(DeviceState 
*dev, Error **errp)


  sysbus_add_io(sbd, 0xcfc, &s->data_mem);
  sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if (g_strcmp0(object_property_get_str(qdev_get_machine(), 
"iommu", NULL),

+  "amd") == 0) {


You can use the Machine wrapper and it will look slightly better (at 
least you get rid of the literal):
MACHINE(qdev_get_machine())->iommu  <=> 
object_property_get_str(qdev_get_machine(), "iommu", NULL)



By the way, does i440fx host work with AMD iommu?



Forgot,...

Yeah, I checked this to confirm it works though looking at it, it seems 
like i440fx doesn't support PCIE(MSI) so interrupt related things might 
not work here but we're not yet there.





+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
  }

  static void i440fx_realize(PCIDevice *dev, Error **errp)
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 1fb4707..dd4c822 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
  #include "hw/hw.h"
  #include "hw/pci-host/q35.h"
  #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"

/
   * Q35 host
@@ -505,10 +506,21 @@ static void mch_realize(PCIDevice *d, Error 
**errp)

   mch->pci_address_space, &mch->pam_regions[i+1],
   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
  }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+char *iommu = object_property_get_str(qdev_get_machine(), 
"iommu", NULL);

+
+if (g_strcmp0(iommu, "intel") == 0) {
+/* Intel IOMMU (VT-d) */
  mch_init_dmar(mch);
+} else if (g_strcmp0(iommu, "amd") == 0) {


Last thing, maybe you can define "intel" and "amd" literals in one 
please,

then use it them as you see fit.


Thanks,
Marcel



+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
  }
+g_free(iommu);
  }

  uint64_t mch_mcfg_base(void)








Re: [Qemu-devel] [V4 2/4] hw/core: Add AMD IO MMU to machine properties

2016-01-18 Thread David Kiarie



On 1/18/2016 7:21 PM, Marcel Apfelbaum wrote:

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

Add IO MMU as a string to machine properties which
is used to control whether and the type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---
  hw/core/machine.c | 17 +
  include/hw/boards.h   |  3 ++-
  include/hw/i386/intel_iommu.h |  1 +
  qemu-options.hx   |  6 +++---
  util/qemu-config.c|  4 ++--
  vl.c  |  8 
  6 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c46ddc7..cb309aa 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -283,18 +283,19 @@ static void machine_set_firmware(Object *obj, 
const char *value, Error **errp)

  ms->firmware = g_strdup(value);
  }

-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
  {
  MachineState *ms = MACHINE(obj);

-return ms->iommu;
+return g_strdup(ms->iommu);
  }

-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, Error 
**errp)

  {
  MachineState *ms = MACHINE(obj);

-ms->iommu = value;
+g_free(ms->iommu);
+ms->iommu = g_strdup(value);
  }

  static void machine_set_suppress_vmdesc(Object *obj, bool value, 
Error **errp)

@@ -454,11 +455,10 @@ static void machine_initfn(Object *obj)
  object_property_set_description(obj, "firmware",
  "Firmware image",
  NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, 
NULL);

  object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable 
Intel IOMMU (VT-d)",

+"IOMMU list",
  NULL);
  object_property_add_bool(obj, "suppress-vmdesc",
   machine_get_suppress_vmdesc,
@@ -484,6 +484,7 @@ static void machine_finalize(Object *obj)
  g_free(ms->dumpdtb);
  g_free(ms->dt_compatible);
  g_free(ms->firmware);
+g_free(ms->iommu);
  }

  bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
  bool machine_kernel_irqchip_allowed(MachineState *machine);
  bool machine_kernel_irqchip_required(MachineState *machine);
  bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
  int machine_kvm_shadow_mem(MachineState *machine);
  int machine_phandle_start(MachineState *machine);
  bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
  bool usb_disabled;
  bool igd_gfx_passthru;
  char *firmware;
-bool iommu;
+char *iommu;
  bool suppress_vmdesc;

  ram_addr_t ram_size;
diff --git a/include/hw/i386/intel_iommu.h 
b/include/hw/i386/intel_iommu.h

index 5dbadb7..0b32bd6 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -27,6 +27,7 @@
  #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
  #define INTEL_IOMMU_DEVICE(obj) \
   OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"

  /* DMAR Hardware Unit Definition address (IOMMU unit) */
  #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
diff --git a/qemu-options.hx b/qemu-options.hx
index 215d00d..ac327c8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
  "kvm_shadow_mem=size of KVM shadow MMU\n"
  "dump-guest-core=on|off include guest memory in 
a core dump (default=on)\n"
  "mem-merge=on|off controls memory merge support 
(default: on)\n"
-"iommu=on|off controls emulated Intel IOMMU 
(VT-d) support (default=off)\n"
+"iommu=amd|intel enables and selects the 
emulated IO MMU (default: off)\n"
  "igd-passthru=on|off controls IGD GFX 
passthrough support (default=off)\n"
  "aes-key-wrap=on|off controls support for AES 
key wrapping (default=on)\n"
  "dea-key-wrap=on|off controls support for DEA 
key wrapping (default=on)\n"
@@ -72,8 +72,8 @@ Include guest memory in a core dump. The default is 
on.

Re: [Qemu-devel] [V4 2/4] hw/core: Add AMD IO MMU to machine properties

2016-01-18 Thread David Kiarie



On 1/18/2016 8:27 PM, Marcel Apfelbaum wrote:

On 01/18/2016 06:48 PM, David Kiarie wrote:



On 1/18/2016 7:21 PM, Marcel Apfelbaum wrote:

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

Add IO MMU as a string to machine properties which
is used to control whether and the type of IO MMU
to emulate

Signed-off-by: David Kiarie 
---
  hw/core/machine.c | 17 +
  include/hw/boards.h   |  3 ++-
  include/hw/i386/intel_iommu.h |  1 +
  qemu-options.hx   |  6 +++---
  util/qemu-config.c|  4 ++--
  vl.c  |  8 
  6 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c46ddc7..cb309aa 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -283,18 +283,19 @@ static void machine_set_firmware(Object *obj, 
const char *value, Error **errp)

  ms->firmware = g_strdup(value);
  }

-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
  {
  MachineState *ms = MACHINE(obj);

-return ms->iommu;
+return g_strdup(ms->iommu);
  }

-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, 
Error **errp)

  {
  MachineState *ms = MACHINE(obj);

-ms->iommu = value;
+g_free(ms->iommu);
+ms->iommu = g_strdup(value);
  }

  static void machine_set_suppress_vmdesc(Object *obj, bool value, 
Error **errp)

@@ -454,11 +455,10 @@ static void machine_initfn(Object *obj)
  object_property_set_description(obj, "firmware",
  "Firmware image",
  NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, 
NULL);

  object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable 
Intel IOMMU (VT-d)",

+"IOMMU list",
  NULL);
  object_property_add_bool(obj, "suppress-vmdesc",
   machine_get_suppress_vmdesc,
@@ -484,6 +484,7 @@ static void machine_finalize(Object *obj)
  g_free(ms->dumpdtb);
  g_free(ms->dt_compatible);
  g_free(ms->firmware);
+g_free(ms->iommu);
  }

  bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
  bool machine_kernel_irqchip_allowed(MachineState *machine);
  bool machine_kernel_irqchip_required(MachineState *machine);
  bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
  int machine_kvm_shadow_mem(MachineState *machine);
  int machine_phandle_start(MachineState *machine);
  bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
  bool usb_disabled;
  bool igd_gfx_passthru;
  char *firmware;
-bool iommu;
+char *iommu;
  bool suppress_vmdesc;

  ram_addr_t ram_size;
diff --git a/include/hw/i386/intel_iommu.h 
b/include/hw/i386/intel_iommu.h

index 5dbadb7..0b32bd6 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -27,6 +27,7 @@
  #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
  #define INTEL_IOMMU_DEVICE(obj) \
   OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"

  /* DMAR Hardware Unit Definition address (IOMMU unit) */
  #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
diff --git a/qemu-options.hx b/qemu-options.hx
index 215d00d..ac327c8 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
  "kvm_shadow_mem=size of KVM shadow MMU\n"
  "dump-guest-core=on|off include guest memory 
in a core dump (default=on)\n"
  "mem-merge=on|off controls memory merge 
support (default: on)\n"
-"iommu=on|off controls emulated Intel IOMMU 
(VT-d) support (default=off)\n"
+"iommu=amd|intel enables and selects the 
emulated IO MMU (default: off)\n"
  "igd-passthru=on|off controls IGD GFX 
passthrough support (default=off)\n"
  "aes-key-wrap=on|off controls support for AES 
key wrapping (default=on)\n"
  "dea-key-wrap=on|off controls support for DEA 
key wrapping (d

[Qemu-devel] [V6 0/4] AMD IOMMU

2016-02-21 Thread David Kiarie
Hello there,

Repost, AMD IOMMU patches version 6.

Changes since version 5
 -Fixed macro formating issues
 -changed occurences of IO MMU to IOMMU for consistency
 -Fixed capability registers duplication
 -Rebased to current master

David Kiarie (4):
  hw/i386: Introduce AMD IOMMU
  hw/core: Add AMD IOMMU to machine properties
  hw/i386: ACPI table for AMD IOMMU
  hw/pci-host: Emulate AMD IOMMU

 hw/core/machine.c |   28 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |  208 +-
 hw/i386/amd_iommu.c   | 1432 +
 hw/i386/amd_iommu.h   |  395 
 hw/pci-host/piix.c|1 +
 hw/pci-host/q35.c |   14 +-
 include/hw/acpi/acpi-defs.h   |   55 ++
 include/hw/boards.h   |3 +-
 include/hw/i386/intel_iommu.h |1 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |6 +-
 util/qemu-config.c|4 +-
 13 files changed, 2123 insertions(+), 27 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [V6 2/4] hw/core: Add AMD IOMMU to machine properties

2016-02-21 Thread David Kiarie
Add IOMMU as a string to machine properties which is
used to control whether and the type of IOMMU to emulate

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 28 
 include/hw/boards.h |  3 ++-
 qemu-options.hx |  6 +++---
 util/qemu-config.c  |  4 ++--
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 6d1a0d8..001ace9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -14,6 +14,8 @@
 #include "hw/boards.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -284,18 +286,28 @@ static void machine_set_firmware(Object *obj, const char 
*value, Error **errp)
 ms->firmware = g_strdup(value);
 }
 
-static bool machine_get_iommu(Object *obj, Error **errp)
+static char *machine_get_iommu(Object *obj, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
 
-return ms->iommu;
+return g_strdup(ms->iommu);
 }
 
-static void machine_set_iommu(Object *obj, bool value, Error **errp)
+static void machine_set_iommu(Object *obj, const char *value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
+Error *err = NULL;
+
+g_free(ms->iommu);
+
+if (g_strcmp0(value, AMD_IOMMU_STR) &&
+g_strcmp0(value, INTEL_IOMMU_STR)) {
+error_setg(errp, "Invalid IOMMU type %s", value);
+error_propagate(errp, err);
+return;
+}
 
-ms->iommu = value;
+ms->iommu = g_strdup(value);
 }
 
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
@@ -455,11 +467,10 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "firmware",
 "Firmware image",
 NULL);
-object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+object_property_add_str(obj, "iommu",
+machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"IOMMU list",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
@@ -485,6 +496,7 @@ static void machine_finalize(Object *obj)
 g_free(ms->dumpdtb);
 g_free(ms->dt_compatible);
 g_free(ms->firmware);
+g_free(ms->iommu);
 }
 
 bool machine_usb(MachineState *machine)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..b119245 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 bool machine_kernel_irqchip_split(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
 int machine_phandle_start(MachineState *machine);
 bool machine_dump_guest_core(MachineState *machine);
@@ -126,7 +127,7 @@ struct MachineState {
 bool usb_disabled;
 bool igd_gfx_passthru;
 char *firmware;
-bool iommu;
+char *iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
diff --git a/qemu-options.hx b/qemu-options.hx
index 2f0465e..dad160f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=amd|intel enables and selects the emulated IOMMU 
(default: off)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -72,8 +72,8 @@ Include guest memory in a core dump. The default is on.
 Enables or disables memory merge support. This feature, when supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
-@item iommu=on|off
-Ena

[Qemu-devel] [V6 3/4] hw/i386: ACPI table for AMD IOMMU

2016-02-21 Thread David Kiarie
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, &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)
+{
+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);
+build_piix4_pci_hotplug(dsdt

[Qemu-devel] [V6 1/4] hw/i386: Introduce AMD IOMMU

2016-02-21 Thread David Kiarie
Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
mininal IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1432 +
 hw/i386/amd_iommu.h   |  395 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1830 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..3dac043
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1432 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+uint64_t romask = ldq_le_p(&s->romask[addr]);
+uint64_t w1cmask = ldq_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldq_le_p(&s->mmior[addr]);
+stq_le_p(&s->

[Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-02-21 Thread David Kiarie
Add AMD IOMMU emulation support to q35 chipset

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c|  1 +
 hw/pci-host/q35.c | 14 --
 include/hw/i386/intel_iommu.h |  1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 41aa66f..ab2e24a 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -36,6 +36,7 @@
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
 #include "qemu/error-report.h"
+#include "hw/i386/amd_iommu.h"
 
 /*
  * I440FX chipset data sheet.
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 115fb8c..355fb32 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) == 0) {
+/* Intel IOMMU (VT-d) */
 mch_init_dmar(mch);
+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, AMD_IOMMU_STR)
+   == 0) {
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
 }
 }
 
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index b024ffa..539530c 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -27,6 +27,7 @@
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
-- 
2.1.4




Re: [Qemu-devel] [V6 3/4] hw/i386: ACPI table for AMD IOMMU

2016-02-21 Thread David Kiarie
On Sun, Feb 21, 2016 at 9:20 PM, Jan Kiszka  wrote:
> 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, &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)
>> +   

[Qemu-devel] [PATCH 3/4] hw/i386: ACPI table for AMD IOMMU

2016-02-21 Thread David Kiarie
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU

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 4554eb8..76ef75f 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,78 @@ 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, &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, 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 GArray *
 build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
 {
@@ -2570,16 +2649,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());
@@ -2600,6 +2669,7 @@ void acpi_build(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;
 AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
@@ -2666,7 +2736,13 @@ void acpi_build(AcpiBuildTables *tables)
 acpi_add_table(table_offsets, tables_blob);
 build_mcfg_q35(tables_blob, tables->linker, &mc

Re: [Qemu-devel] [V6 0/4] AMD IOMMU

2016-02-21 Thread David Kiarie
On Sun, Feb 21, 2016 at 11:20 PM, Jan Kiszka  wrote:
> On 2016-02-21 19:10, David Kiarie wrote:
>> Hello there,
>>
>> Repost, AMD IOMMU patches version 6.
>>
>> Changes since version 5
>>  -Fixed macro formating issues
>>  -changed occurences of IO MMU to IOMMU for consistency
>>  -Fixed capability registers duplication
>>  -Rebased to current master
>
> I suspect this still has some subtle bugs: I'm running the patches over
> master with standard Linux distro as guest, full desktop, and I'm
> getting sporadic segfaults of arbitrary programs. These disappear once I
> disable the IOMMU or switch to the Intel version.

Is this L1 guest or L2 guest ? - haven't got any such so far.

>
> How did you test so far?

I mainly test by logging. I've tested L1 without any iommu-related
command line parameters and with L1 with 'iommu=1 iommu=pt'. L2 guest;
passed-through a device checked it's working correctly, that all.
These guests barely have any load though.

>
> Jan
>
>



Re: [Qemu-devel] [V6 0/4] AMD IOMMU

2016-02-22 Thread David Kiarie
On Mon, Feb 22, 2016 at 10:29 AM, Jan Kiszka  wrote:
> On 2016-02-22 06:57, David Kiarie wrote:
>> On Sun, Feb 21, 2016 at 11:20 PM, Jan Kiszka  wrote:
>>> On 2016-02-21 19:10, David Kiarie wrote:
>>>> Hello there,
>>>>
>>>> Repost, AMD IOMMU patches version 6.
>>>>
>>>> Changes since version 5
>>>>  -Fixed macro formating issues
>>>>  -changed occurences of IO MMU to IOMMU for consistency
>>>>  -Fixed capability registers duplication
>>>>  -Rebased to current master
>>>
>>> I suspect this still has some subtle bugs: I'm running the patches over
>>> master with standard Linux distro as guest, full desktop, and I'm
>>> getting sporadic segfaults of arbitrary programs. These disappear once I
>>> disable the IOMMU or switch to the Intel version.
>>
>> Is this L1 guest or L2 guest ? - haven't got any such so far.
>
> It's L1 only.
>
>>
>>>
>>> How did you test so far?
>>
>> I mainly test by logging. I've tested L1 without any iommu-related
>> command line parameters and with L1 with 'iommu=1 iommu=pt'. L2 guest;
>> passed-through a device checked it's working correctly, that all.
>> These guests barely have any load though.
>
> I quickly reproduced the issue by starting some "heavier" applications,
> a browser or an office suite. Something is apparently always corrupted
> then, data or code, thus the crashes.

Can't reproduce this issue with my ubuntu/debian VMs. Are you using
any iommu-related command line parameters ?

>
> Jan
>
>



Re: [Qemu-devel] [V6 1/4] hw/i386: Introduce AMD IOMMU

2016-02-25 Thread David Kiarie
On Thu, Feb 25, 2016 at 6:43 PM, Marcel Apfelbaum  wrote:
> On 02/21/2016 08:10 PM, David Kiarie wrote:
>>
>> Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
>> The IOMMU does basic translation, error checking and has a
>> mininal IOTLB implementation
>
>
> Hi,
>
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/i386/Makefile.objs |1 +
>>   hw/i386/amd_iommu.c   | 1432
>> +
>>   hw/i386/amd_iommu.h   |  395 ++
>>   include/hw/pci/pci.h  |2 +
>>   4 files changed, 1830 insertions(+)
>>   create mode 100644 hw/i386/amd_iommu.c
>>   create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>   obj-y += pc.o pc_piix.o pc_q35.o
>>   obj-y += pc_sysfw.o
>>   obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>   obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..3dac043
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1432 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +/*#define DEBUG_AMD_IOMMU*/
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +typedef struct AMDIOMMUAddressSpace {
>> +uint8_t bus_num;/* bus number
>> */
>> +uint8_t devfn;  /* device function
>> */
>> +AMDIOMMUState *iommu_state; /* IOMMU - one per machine
>> */
>> +MemoryRegion iommu; /* Device's iommu region
>> */
>> +AddressSpace as;/* device's corresponding address space
>> */
>> +} AMDIOMMUAddressSpace;
>> +
>> +/* IOMMU cache entry */
>> +typedef struct IOMMUIOTLBEntry {
>> +uint64_t gfn;
>> +uint16_t domid;
>> +uint64_t devid;
>> +uint64_t perms;
>> +uint64_t translated_addr;
>> +} IOMMUIOTLBEntry;
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t
>> val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +stq_le_p(&s->romask[addr], romask);
>> +stq_le_p(&s->w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);

[Qemu-devel] Allocate PCI MMIO without BAR requests.

2015-06-26 Thread David kiarie
Hi all,

Some efforts to emulate AMD IOMMU have being going over the past few months.

In real hardware AMD IOMMU is implemented as a PCI function. When
emulating it in Qemu we want to allocate it MMIO space but real AMD
IOMMU manage to reserve memory without making a BAR request, probably
through a static address that's written by the device.(This is
something similar to what non-PCI bus devices do).Trying to reserve
memory via a BAR request results in address conflicts(in Linux) and
all other PCI devices reserve platform resources via BAR requests.

I would like to hear suggestions on how to reserve a memory region for
the device without making a BAR request.

Cheers,
David.



Re: [Qemu-devel] Aspirant for AMD IOMMU emulation project for Outreachy

2015-09-08 Thread David kiarie
On Wed, Sep 9, 2015 at 12:35 AM, Jan Kiszka  wrote:
> [thanks for forwarding, Peter]
>
> Hi Rita,
>
> On 2015-09-08 10:11, Peter Maydell wrote:
>> On 7 September 2015 at 22:31, Rita Sinha  wrote:
>>> Hi Jan,
>>>
>>> I am interested in participating in next round of Outreachy program
>>> with AMD IOMMU emulation project.
>>>
>>>
>>> I have worked on BIOS projects which includes coreboot SeaBios etc and
>>> bootloaders like u-boot and grub. I have experience of working with
>>> qemu and feel that this project is the right match for my skillset.
>>> Kindly guide me how to go ahead with this.
>
> The particular AMD IOMMU project moved on since we listed it. I'm CC'ing
> David, who is currently working on it and just recently posted related
> patches, and Valentine who probably oversees the status better than I
> (due to my lacking involvement recently). David, maybe you can briefly
> comment on status and plans of your work.

Hi all,

Most recent work is here
http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg02759.html
. Most the code is Qemu device boilerplate(so there are a ton of
things to add but I wanted to have the existing work merged first).
The IOMMU just offers basic translation. From Valentine's previous
comments, I only have a few minor issues to fix in the code.

I obviously do other things alongside :-D this project but given some
time I could get the code merged and continue to add other features.

>
> For the Outreachy program, just like for GSoC, we need to find a good
> topic that is sufficiently clear defined on program start and not worked
> on in parallel during the runtime. There are still a number of open
> topics in this area, e.g. around the older Intel IOMMU model (error
> handling and reporting, interrupt remapping), or maybe we find something
> different - depends on your interests and experiences. Do you have any
> public references to your previous work?
>
> Then I'd suggest to schedule an irc meeting to discuss your interests
> and background a bit further and consider available options.
>
> Jan
>



Re: [Qemu-devel] Aspirant for AMD IOMMU emulation project for Outreachy

2015-09-08 Thread David kiarie
On Wed, Sep 9, 2015 at 8:01 AM, Rita Sinha  wrote:
> Hi David,
>
> Please find my response inline.
>
>
>>
>> Hi all,
>>
>> Most recent work is here
>> http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg02759.html
>> . Most the code is Qemu device boilerplate(so there are a ton of
>> things to add but I wanted to have the existing work merged first).
>> The IOMMU just offers basic translation. From Valentine's previous
>> comments, I only have a few minor issues to fix in the code.
>>
>> I obviously do other things alongside :-D this project but given some
>> time I could get the code merged and continue to add other features.
>>
>
> Let me know if I can help in this effort which will help me get
> started on this project.

Hi Rita,

Most likely than not you'll work on the Intel IOMMU and I would
suggest, if you wish to get your feet dirty, just start right away
with the Intel IOMMU (In which case Jan could direct you better)
instead of the AMD one.

>
> Regards,
> Rita Sinha



Re: [Qemu-devel] Aspirant for AMD IOMMU emulation project for Outreachy

2015-09-08 Thread David kiarie
On Wed, Sep 9, 2015 at 9:47 AM, Valentine Sinitsyn
 wrote:
> Hi all,
>
>
> On 09.09.2015 09:23, David kiarie wrote:
>>
>> On Wed, Sep 9, 2015 at 12:35 AM, Jan Kiszka  wrote:
>>>
>>> [thanks for forwarding, Peter]
>>>
>>> Hi Rita,
>>>
>>> On 2015-09-08 10:11, Peter Maydell wrote:
>>>>
>>>> On 7 September 2015 at 22:31, Rita Sinha  wrote:
>>>>>
>>>>> Hi Jan,
>>>>>
>>>>> I am interested in participating in next round of Outreachy program
>>>>> with AMD IOMMU emulation project.
>>>>>
>>>>>
>>>>> I have worked on BIOS projects which includes coreboot SeaBios etc and
>>>>> bootloaders like u-boot and grub. I have experience of working with
>>>>> qemu and feel that this project is the right match for my skillset.
>>>>> Kindly guide me how to go ahead with this.
>>>
>>>
>>> The particular AMD IOMMU project moved on since we listed it. I'm CC'ing
>>> David, who is currently working on it and just recently posted related
>>> patches, and Valentine who probably oversees the status better than I
>>> (due to my lacking involvement recently). David, maybe you can briefly
>>> comment on status and plans of your work.
>>
>>
>> Hi all,
>>
>> Most recent work is here
>> http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg02759.html
>> . Most the code is Qemu device boilerplate(so there are a ton of
>> things to add but I wanted to have the existing work merged first).
>> The IOMMU just offers basic translation. From Valentine's previous
>> comments, I only have a few minor issues to fix in the code.
>
> This is a bit of off-topic here, but I'd argue they are minor. There are
> some inaccuracies in emulation, and IOMMU itself is rather feature-limited,
> just as you said. I doubt I'd be able to run current Jailhouse
> implementation on it, for instance, albeit I haven't tried. So, your patches
> are good start, but I feel there's a somewhat long way before they actually
> get merged.

Yep, that is possible. For instance, you were insisting on 'cache'
implemention ;) which IMHO, is optional but could be a good project
start.

>
> So, in short: there are still tasks to be done in AMD IOMMU emulation
> project. I also feel it's possible to parallelize them so David and Rita can
> continue without stepping at each other toe, if the program permits it.
>
>> I obviously do other things alongside :-D this project but given some
>> time I could get the code merged and continue to add other features.
>>
>>>
>>> For the Outreachy program, just like for GSoC, we need to find a good
>>> topic that is sufficiently clear defined on program start and not worked
>>> on in parallel during the runtime. There are still a number of open
>>> topics in this area, e.g. around the older Intel IOMMU model (error
>>> handling and reporting, interrupt remapping), or maybe we find something
>>> different - depends on your interests and experiences. Do you have any
>>> public references to your previous work?
>>>
>>> Then I'd suggest to schedule an irc meeting to discuss your interests
>>> and background a bit further and consider available options.
>>>
>>> Jan
>>>
>
> Regards,
> Valentine



Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-09-09 Thread David kiarie
On Mon, Sep 7, 2015 at 3:46 PM, Valentine Sinitsyn
 wrote:
> Hi David,
>
> Sorry for the long silence. I've skimmed through your patch, below are some
> thoughts. Please remember I'm looking for IOMMU implementation details, not
> how it is integrated with QEMU.
>
> On 25.08.2015 04:19, David Kiarie wrote:
>>
>> From: David 
>>
>> Add AMD IOMMU emulation to Qemu. This is a very basic AMD IOMMU
>> emulation that only does translation and some basic Event logging.
>> Guest translation enables nested PCI passthrough
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/i386/Makefile.objs |   1 +
>>   hw/i386/amd_iommu.c   | 993
>> ++
>>   hw/i386/amd_iommu.h   | 298 +++
>>   3 files changed, 1292 insertions(+)
>>   create mode 100644 hw/i386/amd_iommu.c
>>   create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index ebd1015..2bae11c 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>   obj-y += pc.o pc_piix.o pc_q35.o
>>   obj-y += pc_sysfw.o
>>   obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>   obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..a3a0b20
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,993 @@
>> +/*
>> + * QEMU emulation of an AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +#define PCI_EXT_CAP_ID_PASID 0x1B
>> +#define PCI_EXT_CAP_ID_PRI   0x13
>
> Do you really need those? They don't seem to be used.
>>
>> +
>> +#define PCI_SLOT(devfn)  (((devfn) >> 3) & 0x1f)
>> +#define PCI_FUNC(devfn)  ((devfn) & 0x07)
>> +
>> +#define MAX_VA_ADDR  (64UL << 5)
>> +#define MAX_PH_ADDR  (48UL << 8)
>> +#define MAX_GVA_ADDR (64UL << 15)
>> +
>> +//#define DEBUG_AMD_IOMMU
>
> It's generally advisable to avoid commented-out lines. Use #ifdefs, or
> remove them altogether.
>
>
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) |
>> IOMMU_DBGBIT(MMIO);
>> +//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) |
>> IOMMU_DBGBIT(COMMAND);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* helper functions - FIXME - provide for reading one byte */
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +stw_le_p(&s->mmior[addr], val);
>> +}
>&g

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-09-09 Thread David kiarie
On Wed, Sep 9, 2015 at 10:45 AM, Valentine Sinitsyn
 wrote:
> On 09.09.2015 12:30, David kiarie wrote:
> ...snip...
>
>
>>>> +static void amd_iommu_cmdbuf_exec(AMDIOMMUState *s)
>>>> +{
>>>> +unsigned type;
>>>> +uint8_t cmd[IOMMU_COMMAND_SIZE];
>>>> +
>>>> +IOMMU_DPRINTF(COMMAND, "");
>>>> +memset(cmd, 0, IOMMU_COMMAND_SIZE);
>>>> +
>>>> +if(dma_memory_read(&address_space_memory, s->cmdbuf +
>>>> s->cmdbuf_head,
>>>> cmd, IOMMU_COMMAND_SIZE)){
>>>> +IOMMU_DPRINTF(COMMAND, "error: fail to access memory at
>>>> 0x%"PRIx64
>>>> +  " + %"PRIu8, s->cmdbuf, s->cmdbuf_head);
>>>> +}
>>>> +
>>>> +type = cmd[CMDBUF_ID_BYTE] >> CMDBUF_ID_RSHIFT;
>>>> +
>>>> +switch(type){
>>>> +case CMD_COMPLETION_WAIT:
>>>> +/* pretend to wait for command execution to complete */
>>>> +IOMMU_DPRINTF(COMMAND, "completion wait requested");
>>>> +amd_iommu_completion_wait(s, cmd);
>>>> +break;
>>>> +case CMD_INVAL_DEVTAB_ENTRY:
>>>> +/* Not implemented yet - should just clear device table
>>>> contents */
>>>> +IOMMU_DPRINTF(COMMAND, "device table entries invalidated");
>>>
>>>
>>> Better make it clear that these commands are not implemented yet. An
>>> IOMMU
>>> is hardly usable without invalidators.
>>
>>
>> I think the "debug prinft" here is misleading. AFAIK, the commands
>> listed here(there are others which I haven't listed) relate to 'cache'
>> which means this commands do nothing in the absence of cache.
>>
>> The reason why I advertise 'cache' is because the linux driver checks
>> for cache and other optional features to determine the IOMMU version
>> whereby versions 2 of IOMMU are assummed to support this features.
>
> Did you check how address translation is emulated in QEMU. I didn't :) But
> you return IOMMTLBEntry from your translation routine, and I'd rather ensure
> it is not cached in some other layer.

Am expected to cache the IOMMUTLBEntries myself, probably through a
hashtable. Also, that's what emulated VT-d in Qemu does.

>
> Besides, omitting invalidation commands will be a problem on real hardware.
> As IOMMU emulation is mainly useful for debugging, I'd reproduce this
> behaviour in the emulator. I mean, if I forget to do CMD_INVAL_DEVTAB_ENTRY
> in my guest code, things shouldn't work properly.

Yes, 'cache' is important for debugging. I or someone else could work
on cache, now or later.

>
> You can just copy all data structures to AMDIOMMUState and use this "cahced"
> copies, updated when you run invalidation commands. But this isn't a #1
> priority, you are right.
>
> Can you share some tests results for this code?

Do you mean the whole IOMMU?It works, as far as am concerned. I got
was able to 'passthrough' a sound device but that's the only device I
tested.

>
>>
>>>
>>>> +break;
>>>> +case CMD_INVAL_IOMMU_PAGES:
>>>> +/* invalidate IOMMU cache for a particular domain */
>>>> +IOMMU_DPRINTF(COMMAND, "IOMMU pages invalidated");
>>>> +break;
>>>> +case CMD_INVAL_IOTLB_PAGES:
>>>> +/* Only present if remote IOTLB present */
>>>> +IOMMU_DPRINTF(COMMAND, "IOTLB pages invalidated");
>>>> +break;
>>>> +case CMD_INVAL_INTR_TABLE:
>>>> +/* no support for interrupt remapping yet */
>>>> +IOMMU_DPRINTF(COMMAND, "interrupt table invalidated");
>>>> +break;
>>>> +default:
>>>> +IOMMU_DPRINTF(COMMAND, "unhandled command %d", type);
>>>> +break;
>>>> +}
>>>> +
>>>> +}
>>>> +
>>>> +static void amd_iommu_cmdbuf_run(AMDIOMMUState *s)
>>>> +{
>>>> +IOMMU_DPRINTF(COMMAND, "");
>>>> +
>>>> +uint64_t *mmio_cmdbuf_head = (uint64_t*)s->mmior +
>>>> MMIO_COMMAND_HEAD;
>>>> +
>>>> +if(!s->cmdbuf_enabled){
>>>> +IOM

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-09-09 Thread David kiarie
I wrote something basic on the cover letter
http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg02759.html

On Wed, Sep 9, 2015 at 11:07 AM, Valentine Sinitsyn
 wrote:
> On 09.09.2015 12:59, David kiarie wrote:
>>
>> On Wed, Sep 9, 2015 at 10:45 AM, Valentine Sinitsyn
>>  wrote:
>>>
>>> On 09.09.2015 12:30, David kiarie wrote:
>>> ...snip...
>>>
>>>
>>>>>> +static void amd_iommu_cmdbuf_exec(AMDIOMMUState *s)
>>>>>> +{
>>>>>> +unsigned type;
>>>>>> +uint8_t cmd[IOMMU_COMMAND_SIZE];
>>>>>> +
>>>>>> +IOMMU_DPRINTF(COMMAND, "");
>>>>>> +memset(cmd, 0, IOMMU_COMMAND_SIZE);
>>>>>> +
>>>>>> +if(dma_memory_read(&address_space_memory, s->cmdbuf +
>>>>>> s->cmdbuf_head,
>>>>>> cmd, IOMMU_COMMAND_SIZE)){
>>>>>> +IOMMU_DPRINTF(COMMAND, "error: fail to access memory at
>>>>>> 0x%"PRIx64
>>>>>> +  " + %"PRIu8, s->cmdbuf, s->cmdbuf_head);
>>>>>> +}
>>>>>> +
>>>>>> +type = cmd[CMDBUF_ID_BYTE] >> CMDBUF_ID_RSHIFT;
>>>>>> +
>>>>>> +switch(type){
>>>>>> +case CMD_COMPLETION_WAIT:
>>>>>> +/* pretend to wait for command execution to complete */
>>>>>> +IOMMU_DPRINTF(COMMAND, "completion wait requested");
>>>>>> +amd_iommu_completion_wait(s, cmd);
>>>>>> +break;
>>>>>> +case CMD_INVAL_DEVTAB_ENTRY:
>>>>>> +/* Not implemented yet - should just clear device table
>>>>>> contents */
>>>>>> +IOMMU_DPRINTF(COMMAND, "device table entries
>>>>>> invalidated");
>>>>>
>>>>>
>>>>>
>>>>> Better make it clear that these commands are not implemented yet. An
>>>>> IOMMU
>>>>> is hardly usable without invalidators.
>>>>
>>>>
>>>>
>>>> I think the "debug prinft" here is misleading. AFAIK, the commands
>>>> listed here(there are others which I haven't listed) relate to 'cache'
>>>> which means this commands do nothing in the absence of cache.
>>>>
>>>> The reason why I advertise 'cache' is because the linux driver checks
>>>> for cache and other optional features to determine the IOMMU version
>>>> whereby versions 2 of IOMMU are assummed to support this features.
>>>
>>>
>>> Did you check how address translation is emulated in QEMU. I didn't :)
>>> But
>>> you return IOMMTLBEntry from your translation routine, and I'd rather
>>> ensure
>>> it is not cached in some other layer.
>>
>>
>> Am expected to cache the IOMMUTLBEntries myself, probably through a
>> hashtable. Also, that's what emulated VT-d in Qemu does.
>>
>>>
>>> Besides, omitting invalidation commands will be a problem on real
>>> hardware.
>>> As IOMMU emulation is mainly useful for debugging, I'd reproduce this
>>> behaviour in the emulator. I mean, if I forget to do
>>> CMD_INVAL_DEVTAB_ENTRY
>>> in my guest code, things shouldn't work properly.
>>
>>
>> Yes, 'cache' is important for debugging. I or someone else could work
>> on cache, now or later.
>>
>>>
>>> You can just copy all data structures to AMDIOMMUState and use this
>>> "cahced"
>>> copies, updated when you run invalidation commands. But this isn't a #1
>>> priority, you are right.
>>>
>>> Can you share some tests results for this code?
>>
>>
>> Do you mean the whole IOMMU?It works, as far as am concerned. I got
>> was able to 'passthrough' a sound device but that's the only device I
>> tested.
>
> That's great. Could you describe your tests setup, please? Maybe in README
> or in the cover letter, so anyone interested could reproduce it just
> following your steps.
>
> Valentine
>
>
>>
>>>
>>>>
>>>>>
>>>>>> +break;
>>>>>> +case CMD_INVAL_IOMMU_PAGES:
>>>>>> +/* 

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-09-09 Thread David kiarie
On Wed, Sep 9, 2015 at 11:14 AM, Valentine Sinitsyn
 wrote:
> Oops, that was a long ago. Sorry & thanks.
No problem.

Will fix all other comments.

>
> Valentine
>
>
> On 09.09.2015 13:12, David kiarie wrote:
>>
>> I wrote something basic on the cover letter
>> http://lists.nongnu.org/archive/html/qemu-devel/2015-08/msg02759.html
>>
>> On Wed, Sep 9, 2015 at 11:07 AM, Valentine Sinitsyn
>>  wrote:
>>>
>>> On 09.09.2015 12:59, David kiarie wrote:
>>>>
>>>>
>>>> On Wed, Sep 9, 2015 at 10:45 AM, Valentine Sinitsyn
>>>>  wrote:
>>>>>
>>>>>
>>>>> On 09.09.2015 12:30, David kiarie wrote:
>>>>> ...snip...
>>>>>
>>>>>
>>>>>>>> +static void amd_iommu_cmdbuf_exec(AMDIOMMUState *s)
>>>>>>>> +{
>>>>>>>> +unsigned type;
>>>>>>>> +uint8_t cmd[IOMMU_COMMAND_SIZE];
>>>>>>>> +
>>>>>>>> +IOMMU_DPRINTF(COMMAND, "");
>>>>>>>> +memset(cmd, 0, IOMMU_COMMAND_SIZE);
>>>>>>>> +
>>>>>>>> +if(dma_memory_read(&address_space_memory, s->cmdbuf +
>>>>>>>> s->cmdbuf_head,
>>>>>>>> cmd, IOMMU_COMMAND_SIZE)){
>>>>>>>> +IOMMU_DPRINTF(COMMAND, "error: fail to access memory at
>>>>>>>> 0x%"PRIx64
>>>>>>>> +  " + %"PRIu8, s->cmdbuf, s->cmdbuf_head);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +type = cmd[CMDBUF_ID_BYTE] >> CMDBUF_ID_RSHIFT;
>>>>>>>> +
>>>>>>>> +switch(type){
>>>>>>>> +case CMD_COMPLETION_WAIT:
>>>>>>>> +/* pretend to wait for command execution to complete */
>>>>>>>> +IOMMU_DPRINTF(COMMAND, "completion wait requested");
>>>>>>>> +amd_iommu_completion_wait(s, cmd);
>>>>>>>> +break;
>>>>>>>> +case CMD_INVAL_DEVTAB_ENTRY:
>>>>>>>> +/* Not implemented yet - should just clear device table
>>>>>>>> contents */
>>>>>>>> +IOMMU_DPRINTF(COMMAND, "device table entries
>>>>>>>> invalidated");
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Better make it clear that these commands are not implemented yet. An
>>>>>>> IOMMU
>>>>>>> is hardly usable without invalidators.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I think the "debug prinft" here is misleading. AFAIK, the commands
>>>>>> listed here(there are others which I haven't listed) relate to 'cache'
>>>>>> which means this commands do nothing in the absence of cache.
>>>>>>
>>>>>> The reason why I advertise 'cache' is because the linux driver checks
>>>>>> for cache and other optional features to determine the IOMMU version
>>>>>> whereby versions 2 of IOMMU are assummed to support this features.
>>>>>
>>>>>
>>>>>
>>>>> Did you check how address translation is emulated in QEMU. I didn't :)
>>>>> But
>>>>> you return IOMMTLBEntry from your translation routine, and I'd rather
>>>>> ensure
>>>>> it is not cached in some other layer.
>>>>
>>>>
>>>>
>>>> Am expected to cache the IOMMUTLBEntries myself, probably through a
>>>> hashtable. Also, that's what emulated VT-d in Qemu does.
>>>>
>>>>>
>>>>> Besides, omitting invalidation commands will be a problem on real
>>>>> hardware.
>>>>> As IOMMU emulation is mainly useful for debugging, I'd reproduce this
>>>>> behaviour in the emulator. I mean, if I forget to do
>>>>> CMD_INVAL_DEVTAB_ENTRY
>>>>> in my guest code, things shouldn't work properly.
>>>>
>>>>
>>>>
>>>> Yes, 'cache' is i

[Qemu-devel] [RFC 1/4] hw/core: Prepare for introducing AMD IOMMU

2015-08-24 Thread David Kiarie
From: David 

Add AMD IOMMU as one of the devices that can possibly be
emulated by Qemu. Also, add some helper functions for
manipulating presence/absence of IOMMU

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 25 +
 include/hw/boards.h |  2 ++
 2 files changed, 27 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index ac4654e..b326a80 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -255,6 +255,20 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static bool machine_get_amd_iommu(Object *obj, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+return ms->amd_iommu;
+}
+
+static void machine_set_amd_iommu(Object *obj, bool value, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+ms->amd_iommu = value;
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -400,6 +414,12 @@ static void machine_initfn(Object *obj)
 object_property_set_description(obj, "iommu",
 "Set on/off to enable/disable Intel IOMMU 
(VT-d)",
 NULL);
+object_property_add_bool(obj, "amd-iommu",
+ machine_get_amd_iommu,
+ machine_set_amd_iommu, NULL);
+object_property_set_description(obj, "amd-iommu",
+"Set on/off to enable/disable AMD-Vi",
+NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
  machine_set_suppress_vmdesc, NULL);
@@ -436,6 +456,11 @@ bool machine_iommu(MachineState *machine)
 return machine->iommu;
 }
 
+bool machine_amd_iommu(MachineState *machine)
+{
+return machine->amd_iommu;
+}
+
 bool machine_kernel_irqchip_allowed(MachineState *machine)
 {
 return machine->kernel_irqchip_allowed;
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 3f84afd..88324b2 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -54,6 +54,7 @@ extern MachineState *current_machine;
 
 bool machine_usb(MachineState *machine);
 bool machine_iommu(MachineState *machine);
+bool machine_amd_iommu(MachineState *machine);
 bool machine_kernel_irqchip_allowed(MachineState *machine);
 bool machine_kernel_irqchip_required(MachineState *machine);
 int machine_kvm_shadow_mem(MachineState *machine);
@@ -139,6 +140,7 @@ struct MachineState {
 bool usb_disabled;
 char *firmware;
 bool iommu;
+bool amd_iommu;
 bool suppress_vmdesc;
 
 ram_addr_t ram_size;
-- 
2.1.4




[Qemu-devel] [RFC 0/4] AMD IOMMU

2015-08-24 Thread David Kiarie
This series implements basic AMD IOMMU emulation to Qemu

AMD IOMMU emulation.
   -This series emulates AMD IOMMU on qemu. It implements the following features
  -Translation - 4K pages
  -Event logging - particulary fault logging.

   -AMD IOMMU, being a convectional PCI device doesn't rely on any other 
technology from AMD and hence you can test this patch on l2 guest emulated on 
an Intel PC.
   -These patches have been tested using the 'ac97' sound device with 
QEMU_AUDIO_DRV=alsa and proven to work.
   
Testing - pretty basic stuff...
On host
#kvm_amd is loaded with nested support by default by anyways :)
   -$modprobe -r kvm_amd
$modprobe kvm_amd nested=1

$command to start guest with 'iommu=1' kernel arguments

On the guest
$dmesg | AMD-Vi

AMD-Vi: Enabling IOMMU at :00:00.2 cap 0x40
AMD-Vi: Lazy IO/TLB flushing enabled

$modprobe kvm_amd

$modprobe pci_stub

$lspci -n 
01:00.0 0200: 8086:10b9 (rev 06)

$echo "8086 10b9" > /sys/bus/pci/drivers/pci-stub/new_id
$echo :01:00.0 > /sys/bus/pci/devices/:01:00.0/driver/unbind
$echo :01:00.0 > /sys/bus/pci/drivers/pci-stub/bind

Assign the device

$/usr/local/bin/qemu-system-x86_64 -m 512 -boot c -net none -hda 
/root/ia32e_rhel5u1.img -device pci-assign,host=01:00.0 

I guess that's all there is to say. Please test!

asla.

David (4):
  hw/core: Prepare for introducing AMD IOMMU
  hw/i386: Introduce AMD IOMMU
  hw/i386: Introduce IVRS for AMD IOMMU
  hw/pci-host: Add AMD IOMMU emulation to q35 and PIIX

 hw/core/machine.c   |  25 ++
 hw/i386/Makefile.objs   |   1 +
 hw/i386/acpi-build.c|  85 
 hw/i386/amd_iommu.c | 993 
 hw/i386/amd_iommu.h | 298 +
 hw/pci-host/piix.c  |  11 +
 hw/pci-host/q35.c   |  11 +
 include/hw/acpi/acpi-defs.h |  55 +++
 include/hw/boards.h |   2 +
 9 files changed, 1481 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-08-24 Thread David Kiarie
From: David 

Add AMD IOMMU emulation to Qemu. This is a very basic AMD IOMMU
emulation that only does translation and some basic Event logging.
Guest translation enables nested PCI passthrough

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |   1 +
 hw/i386/amd_iommu.c   | 993 ++
 hw/i386/amd_iommu.h   | 298 +++
 3 files changed, 1292 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index ebd1015..2bae11c 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..a3a0b20
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,993 @@
+/*
+ * QEMU emulation of an AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+#define PCI_EXT_CAP_ID_PASID 0x1B
+#define PCI_EXT_CAP_ID_PRI   0x13
+
+#define PCI_SLOT(devfn)  (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)  ((devfn) & 0x07)
+
+#define MAX_VA_ADDR  (64UL << 5)
+#define MAX_PH_ADDR  (48UL << 8)
+#define MAX_GVA_ADDR (64UL << 15)
+
+//#define DEBUG_AMD_IOMMU
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) | 
IOMMU_DBGBIT(MMIO);
+//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) | 
IOMMU_DBGBIT(COMMAND);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+/* helper functions - FIXME - provide for reading one byte */
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+stw_le_p(&s->mmior[addr], val);
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+stl_le_p(&s->mmior[addr], val);
+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* execute a completion wait command */
+static void amd_iommu_completion_wait(AMDIOMMUState *s, uint8_t *cmd)
+{
+unsigned int addr;
+
+/* completion store */
+if(cmd[0] & COM_COMPLETION_STORE_MASK){
+addr = le64_to_cpu(*(uint64_t*)cmd) & COM_STORE_ADDRESS_MASK;
+if(dma_memory_write(&address_space_memory, addr, cmd + 8, 8)){
+IOMMU_DPRINTF(ELOG, "error: fail to write at address 0%x"PRIx64, 
addr);
+}
+
+}
+
+/* set completion interrupt */
+if (cmd[0] & COM_COMPLETION_INTR){
+s->mmior[MMIO_STATUS] |= MMIO_STATUS_COMWAIT_INTR;
+}
+}
+
+static void amd_iommu_cmdbuf_exec(AMDIOMMUState *s)
+{
+unsigned type;
+uint8_t cmd[IOMMU_COMMAND_SIZE];
+
+IOMMU_DPRINTF(COMMAND, "");
+memset(cmd, 0, IOMMU_COMMAND_SIZE);
+
+if(dma_memory_read(&address_space_memory, s->cmdbuf + s->cmdbuf_head, cmd, 
IOMMU_COMMAND_SIZE)){
+IOMMU_DPRINTF(COMMAND, "error: fail to access memory at 0x%"PRIx64
+  " + %"PRIu8, s->cmdbuf, s->cmdbuf_head);
+}
+
+type = cmd[CMDBUF_ID_BYTE] >> CMDBUF_ID_RSHIFT;
+
+switch(type){
+case CMD_COMPLETION_WAIT:
+/* pretend to wait for co

[Qemu-devel] [RFC 4/4] hw/pci-host: Add AMD IOMMU emulation to q35 and PIIX

2015-08-24 Thread David Kiarie
From: David 

Add AMD IOMMU emulation to q35 and PIIX chipsets.

Signed-off-by: David Kiarie 
---
 hw/pci-host/piix.c | 11 +++
 hw/pci-host/q35.c  | 11 +++
 2 files changed, 22 insertions(+)

diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 1cb25f3..348cff0 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -31,6 +31,7 @@
 #include "qemu/range.h"
 #include "hw/xen/xen.h"
 #include "hw/pci-host/pam.h"
+#include "hw/i386/amd_iommu.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/ioapic.h"
 #include "qapi/visitor.h"
@@ -292,12 +293,21 @@ static void i440fx_pcihost_realize(DeviceState *dev, 
Error **errp)
 {
 PCIHostState *s = PCI_HOST_BRIDGE(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
 
 sysbus_add_io(sbd, 0xcf8, &s->conf_mem);
 sysbus_init_ioports(sbd, 0xcf8, 4);
 
 sysbus_add_io(sbd, 0xcfc, &s->data_mem);
 sysbus_init_ioports(sbd, 0xcfc, 4);
+
+/* AMD IOMMU (AMD-Vi) */
+if(machine_amd_iommu(current_machine)){
+iommu = pci_create_simple(s->bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(s->bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 static void i440fx_realize(PCIDevice *dev, Error **errp)
@@ -333,6 +343,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
 object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
 qdev_init_nofail(dev);
 
+
 d = pci_create_simple(b, 0, TYPE_I440FX_PCI_DEVICE);
 *pi440fx_state = I440FX_PCI_DEVICE(d);
 f = *pi440fx_state;
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index bd74094..4bb7e3f 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -30,6 +30,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -470,6 +471,8 @@ static void mch_realize(PCIDevice *d, Error **errp)
 {
 int i;
 MCHPCIState *mch = MCH_PCI_DEVICE(d);
+AMDIOMMUState *iommu_state;
+PCIDevice *iommu;
 
 /* setup pci memory mapping */
 pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory,
@@ -528,6 +531,14 @@ static void mch_realize(PCIDevice *d, Error **errp)
 if (machine_iommu(current_machine)) {
 mch_init_dmar(mch);
 }
+
+/* AMD IOMMU (AMD-Vi) */
+if (machine_amd_iommu(current_machine)){
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
+}
 }
 
 uint64_t mch_mcfg_base(void)
-- 
2.1.4




[Qemu-devel] [RFC 3/4] hw/i386: Introduce IVRS for AMD IOMMU

2015-08-24 Thread David Kiarie
From: David 

Add IVRS table for AMD IOMMU. Table indicates that all devices will be
translated by the IOMMU, features common to all IOMMUs and IVDB for the
IOMMU to be emulated

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

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 95e0c65..1016ed9 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -50,6 +50,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/i386/q35-acpi-dsdt.hex"
 #include "hw/i386/acpi-dsdt.hex"
@@ -1576,10 +1577,80 @@ build_dmar_q35(GArray *table_data, GArray *linker)
 }
 
 static void
+amd_iommu_acpi_set_flag(uint8_t *value, uint64_t flag)
+{
+uint64_t newvalue = *value | flag;
+*(uint64_t*)value = newvalue;
+}
+
+static void
+amd_iommu_acpi_set_feature(uint64_t *value, uint64_t feature)
+{
+uint64_t newvalue = *value | feature;
+*value = newvalue;
+}
+
+static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+int iommu_start = table_data->len;
+bool iommu_ambig;
+uint64_t host_width = (AMD_IOMMU_HOST_ADDRESS_WIDTH << 8);
+
+AcpiAMDIOMMUIVRS *ivrs;
+AcpiAMDIOMMUHardwareUnit *iommu;
+
+/* IVRS definition */
+ivrs = acpi_data_push(table_data, sizeof(*ivrs));
+ivrs->revision = ACPI_IOMMU_IVRS_TYPE;
+ivrs->length = (sizeof(*ivrs) + sizeof(*iommu));
+ivrs->v_common_info = host_width;
+
+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 = 0x10;
+/* IVHD flags */
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_HT_TUNEN);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PPRSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_IOTLBSUP);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_ISOC);
+amd_iommu_acpi_set_flag(&iommu->flags, IVHD_PREFSUP);
+
+iommu->length = sizeof(*iommu);
+iommu->device_id = PCI_DEVICE_ID_RD890_IOMMU;
+iommu->capability_offset = s->capab_offset;
+iommu->mmio_base = s->mmio.addr;
+iommu->pci_segment = cpu_to_le16(0);
+iommu->interrupt_info = cpu_to_le16(0);
+
+/* EFR features */
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GTSUP);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_HATS);
+amd_iommu_acpi_set_feature(&iommu->efr_register, IVHD_EFR_GATS);
+
+/* device entries */
+memset(iommu->dev_entries, 0, 20);
+
+/* Add device flags here */
+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);
+}
+
+static void
 build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
 {
 AcpiTableHeader *dsdt;
 
+
 assert(misc->dsdt_code && misc->dsdt_size);
 
 dsdt = acpi_data_push(table_data, misc->dsdt_size);
@@ -1658,6 +1729,16 @@ static bool acpi_has_iommu(void)
 return intel_iommu && !ambiguous;
 }
 
+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 acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 {
@@ -1741,6 +1822,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables 
*tables)
 acpi_add_table(table_offsets, tables_blob);
 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);
+}
 
 /* Add tables supplied by user (if any) */
 for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 2b431e6..4fc1f79 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -561,4 +561,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
+#

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-08-25 Thread David kiarie
On Tue, Aug 25, 2015 at 9:39 AM, Valentine Sinitsyn
 wrote:
> Hi,
>
>
> On 25.08.2015 04:19, David Kiarie wrote:
>>
>> From: David 
>>
>> Add AMD IOMMU emulation to Qemu. This is a very basic AMD IOMMU
>> emulation that only does translation and some basic Event logging.
>> Guest translation enables nested PCI passthrough
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/i386/Makefile.objs |   1 +
>>   hw/i386/amd_iommu.c   | 993
>> ++
>>   hw/i386/amd_iommu.h   | 298 +++
>>   3 files changed, 1292 insertions(+)
>>   create mode 100644 hw/i386/amd_iommu.c
>>   create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index ebd1015..2bae11c 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>   obj-y += pc.o pc_piix.o pc_q35.o
>>   obj-y += pc_sysfw.o
>>   obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>   obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..a3a0b20
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,993 @@
>> +/*
>> + * QEMU emulation of an AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License
>> along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + */
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +#define PCI_EXT_CAP_ID_PASID 0x1B
>> +#define PCI_EXT_CAP_ID_PRI   0x13
>> +
>> +#define PCI_SLOT(devfn)  (((devfn) >> 3) & 0x1f)
>> +#define PCI_FUNC(devfn)  ((devfn) & 0x07)
>> +
>> +#define MAX_VA_ADDR  (64UL << 5)
>> +#define MAX_PH_ADDR  (48UL << 8)
>> +#define MAX_GVA_ADDR (64UL << 15)
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) |
>> IOMMU_DBGBIT(MMIO);
>> +//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) |
>> IOMMU_DBGBIT(COMMAND);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +/* helper functions - FIXME - provide for reading one byte */
>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return lduw_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldl_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
>> +{
>> +return ldq_le_p(&s->mmior[addr]);
>> +}
>> +
>> +static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
>> +{
>> +stw_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
>> +{
>> +stl_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t val)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +}
>> +
>> +/* execute a completion wait command */
>> +static voi

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-08-25 Thread David kiarie
On Tue, Aug 25, 2015 at 10:31 AM, Valentine Sinitsyn
 wrote:
>
>
> On 25.08.2015 12:25, David kiarie wrote:
>>
>> On Tue, Aug 25, 2015 at 9:39 AM, Valentine Sinitsyn
>>  wrote:
>>>
>>> Hi,
>>>
>>>
>>> On 25.08.2015 04:19, David Kiarie wrote:
>>>>
>>>>
>>>> From: David 
>>>>
>>>> Add AMD IOMMU emulation to Qemu. This is a very basic AMD IOMMU
>>>> emulation that only does translation and some basic Event logging.
>>>> Guest translation enables nested PCI passthrough
>>>>
>>>> Signed-off-by: David Kiarie 
>>>> ---
>>>>hw/i386/Makefile.objs |   1 +
>>>>hw/i386/amd_iommu.c   | 993
>>>> ++
>>>>hw/i386/amd_iommu.h   | 298 +++
>>>>3 files changed, 1292 insertions(+)
>>>>create mode 100644 hw/i386/amd_iommu.c
>>>>create mode 100644 hw/i386/amd_iommu.h
>>>>
>>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>>> index ebd1015..2bae11c 100644
>>>> --- a/hw/i386/Makefile.objs
>>>> +++ b/hw/i386/Makefile.objs
>>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>>obj-y += pc.o pc_piix.o pc_q35.o
>>>>obj-y += pc_sysfw.o
>>>>obj-y += intel_iommu.o
>>>> +obj-y += amd_iommu.o
>>>>    obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>>
>>>>obj-y += kvmvapic.o
>>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>>> new file mode 100644
>>>> index 000..a3a0b20
>>>> --- /dev/null
>>>> +++ b/hw/i386/amd_iommu.c
>>>> @@ -0,0 +1,993 @@
>>>> +/*
>>>> + * QEMU emulation of an AMD IOMMU (AMD-Vi)
>>>> + *
>>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>>> + * Copyright (C) 2015 David Kiarie, 
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License as published by
>>>> + * the Free Software Foundation; either version 2 of the License, or
>>>> + * (at your option) any later version.
>>>> +
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> +
>>>> + * You should have received a copy of the GNU General Public License
>>>> along
>>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>>> + *
>>>> + */
>>>> +#include "hw/i386/amd_iommu.h"
>>>> +
>>>> +#define PCI_EXT_CAP_ID_PASID 0x1B
>>>> +#define PCI_EXT_CAP_ID_PRI   0x13
>>>> +
>>>> +#define PCI_SLOT(devfn)  (((devfn) >> 3) & 0x1f)
>>>> +#define PCI_FUNC(devfn)  ((devfn) & 0x07)
>>>> +
>>>> +#define MAX_VA_ADDR  (64UL << 5)
>>>> +#define MAX_PH_ADDR  (48UL << 8)
>>>> +#define MAX_GVA_ADDR (64UL << 15)
>>>> +
>>>> +//#define DEBUG_AMD_IOMMU
>>>> +#ifdef DEBUG_AMD_IOMMU
>>>> +enum {
>>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>>> +};
>>>> +
>>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>>> +static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) |
>>>> IOMMU_DBGBIT(MMIO);
>>>> +//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) |
>>>> IOMMU_DBGBIT(COMMAND);
>>>> +
>>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>>>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>>>> +## __VA_ARGS__); } \
>>>> +} while (0)
>>>> +#else
>>>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>>>> +#endif
>>>> +
>>>> +/* helper functions - FIXME - provide for reading one byte */
>>>> +static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
>>>> +

Re: [Qemu-devel] [RFC 2/4] hw/i386: Introduce AMD IOMMU

2015-08-25 Thread David kiarie
Also, am not sure what HATS, GATS and sizes of virtual addresses(for
both guest and host) I should be using.

On Tue, Aug 25, 2015 at 10:41 AM, David kiarie  wrote:
> On Tue, Aug 25, 2015 at 10:31 AM, Valentine Sinitsyn
>  wrote:
>>
>>
>> On 25.08.2015 12:25, David kiarie wrote:
>>>
>>> On Tue, Aug 25, 2015 at 9:39 AM, Valentine Sinitsyn
>>>  wrote:
>>>>
>>>> Hi,
>>>>
>>>>
>>>> On 25.08.2015 04:19, David Kiarie wrote:
>>>>>
>>>>>
>>>>> From: David 
>>>>>
>>>>> Add AMD IOMMU emulation to Qemu. This is a very basic AMD IOMMU
>>>>> emulation that only does translation and some basic Event logging.
>>>>> Guest translation enables nested PCI passthrough
>>>>>
>>>>> Signed-off-by: David Kiarie 
>>>>> ---
>>>>>hw/i386/Makefile.objs |   1 +
>>>>>hw/i386/amd_iommu.c   | 993
>>>>> ++
>>>>>hw/i386/amd_iommu.h   | 298 +++
>>>>>3 files changed, 1292 insertions(+)
>>>>>create mode 100644 hw/i386/amd_iommu.c
>>>>>create mode 100644 hw/i386/amd_iommu.h
>>>>>
>>>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>>>> index ebd1015..2bae11c 100644
>>>>> --- a/hw/i386/Makefile.objs
>>>>> +++ b/hw/i386/Makefile.objs
>>>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>>>obj-y += pc.o pc_piix.o pc_q35.o
>>>>>obj-y += pc_sysfw.o
>>>>>obj-y += intel_iommu.o
>>>>> +obj-y += amd_iommu.o
>>>>>obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>>>
>>>>>obj-y += kvmvapic.o
>>>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>>>> new file mode 100644
>>>>> index 000..a3a0b20
>>>>> --- /dev/null
>>>>> +++ b/hw/i386/amd_iommu.c
>>>>> @@ -0,0 +1,993 @@
>>>>> +/*
>>>>> + * QEMU emulation of an AMD IOMMU (AMD-Vi)
>>>>> + *
>>>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>>>> + * Copyright (C) 2015 David Kiarie, 
>>>>> + *
>>>>> + * This program is free software; you can redistribute it and/or modify
>>>>> + * it under the terms of the GNU General Public License as published by
>>>>> + * the Free Software Foundation; either version 2 of the License, or
>>>>> + * (at your option) any later version.
>>>>> +
>>>>> + * This program is distributed in the hope that it will be useful,
>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>>> + * GNU General Public License for more details.
>>>>> +
>>>>> + * You should have received a copy of the GNU General Public License
>>>>> along
>>>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>>>> + *
>>>>> + */
>>>>> +#include "hw/i386/amd_iommu.h"
>>>>> +
>>>>> +#define PCI_EXT_CAP_ID_PASID 0x1B
>>>>> +#define PCI_EXT_CAP_ID_PRI   0x13
>>>>> +
>>>>> +#define PCI_SLOT(devfn)  (((devfn) >> 3) & 0x1f)
>>>>> +#define PCI_FUNC(devfn)  ((devfn) & 0x07)
>>>>> +
>>>>> +#define MAX_VA_ADDR  (64UL << 5)
>>>>> +#define MAX_PH_ADDR  (48UL << 8)
>>>>> +#define MAX_GVA_ADDR (64UL << 15)
>>>>> +
>>>>> +//#define DEBUG_AMD_IOMMU
>>>>> +#ifdef DEBUG_AMD_IOMMU
>>>>> +enum {
>>>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>>>> +};
>>>>> +
>>>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>>>> +static int iommu_dbgflags = IOMMU_DBGBIT(GENERAL) | IOMMU_DBGBIT(MMU) |
>>>>> IOMMU_DBGBIT(MMIO);
>>>>> +//| IOMMU_DBGBIT(CAPAB) | IOMMU_DBGBIT(ELOG) | IOMMU_DBGBIT(CACHE) |
>>>>> IOMMU_DBGBIT(COMMAND);
>>>>> +
>>>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>>>> +if (iommu_dbgflags & IOMMU_DBGBIT

Re: [Qemu-devel] [V6 1/4] hw/i386: Introduce AMD IOMMU

2016-03-01 Thread David Kiarie
On Fri, Feb 26, 2016 at 9:23 AM, David Kiarie  wrote:
> On Thu, Feb 25, 2016 at 6:43 PM, Marcel Apfelbaum  wrote:
>> On 02/21/2016 08:10 PM, David Kiarie wrote:
>>>
>>> Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
>>> The IOMMU does basic translation, error checking and has a
>>> mininal IOTLB implementation
>>
>>
>> Hi,
>>
>>>
>>> Signed-off-by: David Kiarie 
>>> ---
>>>   hw/i386/Makefile.objs |1 +
>>>   hw/i386/amd_iommu.c   | 1432
>>> +
>>>   hw/i386/amd_iommu.h   |  395 ++
>>>   include/hw/pci/pci.h  |2 +
>>>   4 files changed, 1830 insertions(+)
>>>   create mode 100644 hw/i386/amd_iommu.c
>>>   create mode 100644 hw/i386/amd_iommu.h
>>>
>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>> index b52d5b8..2f1a265 100644
>>> --- a/hw/i386/Makefile.objs
>>> +++ b/hw/i386/Makefile.objs
>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>   obj-y += pc.o pc_piix.o pc_q35.o
>>>   obj-y += pc_sysfw.o
>>>   obj-y += intel_iommu.o
>>> +obj-y += amd_iommu.o
>>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>
>>>   obj-y += kvmvapic.o
>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>> new file mode 100644
>>> index 000..3dac043
>>> --- /dev/null
>>> +++ b/hw/i386/amd_iommu.c
>>> @@ -0,0 +1,1432 @@
>>> +/*
>>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>>> + *
>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>> + * Copyright (C) 2015 David Kiarie, 
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation; either version 2 of the License, or
>>> + * (at your option) any later version.
>>> +
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> +
>>> + * You should have received a copy of the GNU General Public License
>>> along
>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>> + *
>>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>>> + *
>>> + */
>>> +#include "hw/i386/amd_iommu.h"
>>> +
>>> +/*#define DEBUG_AMD_IOMMU*/
>>> +#ifdef DEBUG_AMD_IOMMU
>>> +enum {
>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>> +};
>>> +
>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>>> +
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>>> +## __VA_ARGS__); } \
>>> +} while (0)
>>> +#else
>>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>>> +#endif
>>> +
>>> +typedef struct AMDIOMMUAddressSpace {
>>> +uint8_t bus_num;/* bus number
>>> */
>>> +uint8_t devfn;  /* device function
>>> */
>>> +AMDIOMMUState *iommu_state; /* IOMMU - one per machine
>>> */
>>> +MemoryRegion iommu; /* Device's iommu region
>>> */
>>> +AddressSpace as;/* device's corresponding address space
>>> */
>>> +} AMDIOMMUAddressSpace;
>>> +
>>> +/* IOMMU cache entry */
>>> +typedef struct IOMMUIOTLBEntry {
>>> +uint64_t gfn;
>>> +uint16_t domid;
>>> +uint64_t devid;
>>> +uint64_t perms;
>>> +uint64_t translated_addr;
>>> +} IOMMUIOTLBEntry;
>>> +
>>> +/* configure MMIO registers at startup/reset */
>>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t
>>> val,
>>> +   uint64_t romask, uint64_t w1cmask)
>>> +{
>>> +stq_le_p(&s->mmior[addr], val);
>>> +stq_le_p(&s->romask[addr], romask);
>>> +s

Re: [Qemu-devel] [V6 1/4] hw/i386: Introduce AMD IOMMU

2016-03-01 Thread David Kiarie
On Wed, Mar 2, 2016 at 7:00 AM, David Kiarie  wrote:
> On Fri, Feb 26, 2016 at 9:23 AM, David Kiarie  wrote:
>> On Thu, Feb 25, 2016 at 6:43 PM, Marcel Apfelbaum  wrote:
>>> On 02/21/2016 08:10 PM, David Kiarie wrote:
>>>>
>>>> Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
>>>> The IOMMU does basic translation, error checking and has a
>>>> mininal IOTLB implementation
>>>
>>>
>>> Hi,
>>>
>>>>
>>>> Signed-off-by: David Kiarie 
>>>> ---
>>>>   hw/i386/Makefile.objs |1 +
>>>>   hw/i386/amd_iommu.c   | 1432
>>>> +
>>>>   hw/i386/amd_iommu.h   |  395 ++
>>>>   include/hw/pci/pci.h  |2 +
>>>>   4 files changed, 1830 insertions(+)
>>>>   create mode 100644 hw/i386/amd_iommu.c
>>>>   create mode 100644 hw/i386/amd_iommu.h
>>>>
>>>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>>>> index b52d5b8..2f1a265 100644
>>>> --- a/hw/i386/Makefile.objs
>>>> +++ b/hw/i386/Makefile.objs
>>>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>>>   obj-y += pc.o pc_piix.o pc_q35.o
>>>>   obj-y += pc_sysfw.o
>>>>   obj-y += intel_iommu.o
>>>> +obj-y += amd_iommu.o
>>>>   obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>>>
>>>>   obj-y += kvmvapic.o
>>>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>>>> new file mode 100644
>>>> index 000..3dac043
>>>> --- /dev/null
>>>> +++ b/hw/i386/amd_iommu.c
>>>> @@ -0,0 +1,1432 @@
>>>> +/*
>>>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>>>> + *
>>>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>>>> + * Copyright (C) 2015 David Kiarie, 
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or modify
>>>> + * it under the terms of the GNU General Public License as published by
>>>> + * the Free Software Foundation; either version 2 of the License, or
>>>> + * (at your option) any later version.
>>>> +
>>>> + * This program is distributed in the hope that it will be useful,
>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>>> + * GNU General Public License for more details.
>>>> +
>>>> + * You should have received a copy of the GNU General Public License
>>>> along
>>>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>>>> + *
>>>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>>>> + *
>>>> + */
>>>> +#include "hw/i386/amd_iommu.h"
>>>> +
>>>> +/*#define DEBUG_AMD_IOMMU*/
>>>> +#ifdef DEBUG_AMD_IOMMU
>>>> +enum {
>>>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>>>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
>>>> +};
>>>> +
>>>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>>>> +static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
>>>> +
>>>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>>>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>>>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>>>> +## __VA_ARGS__); } \
>>>> +} while (0)
>>>> +#else
>>>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>>>> +#endif
>>>> +
>>>> +typedef struct AMDIOMMUAddressSpace {
>>>> +uint8_t bus_num;/* bus number
>>>> */
>>>> +uint8_t devfn;  /* device function
>>>> */
>>>> +AMDIOMMUState *iommu_state; /* IOMMU - one per machine
>>>> */
>>>> +MemoryRegion iommu; /* Device's iommu region
>>>> */
>>>> +AddressSpace as;/* device's corresponding address space
>>>> */
>>>> +} AMDIOMMUAddressSpace;
>>>> +
>>>> +/* IOMMU cache entry */
>>>> +typedef struct IOMMUIOTLBEntry {
>>>> +uint64_t gfn;
>>>> +uint16_t domid;
>>>> +uint64_t devid;
>>>> +uint64_t perms;
>>>> +uint64_t translat

Re: [Qemu-devel] [V6 1/4] hw/i386: Introduce AMD IOMMU

2016-03-02 Thread David Kiarie



On 25/02/16 18:43, Marcel Apfelbaum wrote:

On 02/21/2016 08:10 PM, David Kiarie wrote:

Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
mininal IOTLB implementation


Hi,



Signed-off-by: David Kiarie 
---
  hw/i386/Makefile.objs |1 +
  hw/i386/amd_iommu.c   | 1432 
+

  hw/i386/amd_iommu.h   |  395 ++
  include/hw/pci/pci.h  |2 +
  4 files changed, 1830 insertions(+)
  create mode 100644 hw/i386/amd_iommu.c
  create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
  obj-y += pc.o pc_piix.o pc_q35.o
  obj-y += pc_sysfw.o
  obj-y += intel_iommu.o
+obj-y += amd_iommu.o
  obj-$(CONFIG_XEN) += ../xenpv/ xen/

  obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..3dac043
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1432 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License 
along

+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus 
number   */
+uint8_t devfn;  /* device 
function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per 
machine  */
+MemoryRegion iommu; /* Device's iommu 
region*/
+AddressSpace as;/* device's corresponding address 
space */

+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, 
uint64_t val,

+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, 
hwaddr addr)

+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t 
val)

+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & 
oldval));

+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t 
val)

+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & 
oldval));

+}
+
+static void amd_iommu_writeq(AMDIOMMUState *s, hwaddr addr, uint64_t 
val)

+{
+uint64_t romask = ldq_le_p(&s->romask[addr]);
+uin

Re: [Qemu-devel] [V6 2/4] hw/core: Add AMD IOMMU to machine properties

2016-03-02 Thread David Kiarie



On 21/02/16 23:09, Jan Kiszka wrote:

On 2016-02-21 19:10, David Kiarie wrote:

diff --git a/qemu-options.hx b/qemu-options.hx
index 2f0465e..dad160f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
  "kvm_shadow_mem=size of KVM shadow MMU\n"
  "dump-guest-core=on|off include guest memory in a core dump 
(default=on)\n"
  "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=amd|intel enables and selects the emulated IOMMU 
(default: off)\n"

We should also support "iommu=off" or "none" to explicitly disable it.
That is consistent with other switches, and maybe there will once be a
machine type (chipset) with IOMMU enabled by default.


We could have such but this will not be referenced anywhere in the code 
as the IOMMU is 'off' by default. Most of the other such switches relate 
to properties that are 'on' by default.




Jan






Re: [Qemu-devel] [V6 0/4] AMD IOMMU

2016-03-02 Thread David Kiarie



On 01/03/16 16:48, Jan Kiszka wrote:

On 2016-03-01 14:07, Michael S. Tsirkin wrote:

On Sun, Feb 21, 2016 at 09:10:56PM +0300, David Kiarie wrote:

Hello there,

Repost, AMD IOMMU patches version 6.

Changes since version 5
  -Fixed macro formating issues
  -changed occurences of IO MMU to IOMMU for consistency
  -Fixed capability registers duplication
  -Rebased to current master

David Kiarie (4):
   hw/i386: Introduce AMD IOMMU
   hw/core: Add AMD IOMMU to machine properties
   hw/i386: ACPI table for AMD IOMMU
   hw/pci-host: Emulate AMD IOMMU

I went over AMD IOMMU spec.
I'm concerned that it appears that there's no chance for it to
work correctly if host caches invalid PTE entries.

The spec vaguely discusses write-protecting such PTEs but
that would be very complex if it can be made to work at all.

This means that this can't work with e.g. VFIO.
It can only work with emulated devices.

You mean it can't work if we program a real IOMMU (for VFIO) with
translated data from the emulated one but cannot track any updates of
the related page tables because the guest is not required to issue
traceable flush requests? Hmm, too bad.


OTOH VTD can easily support PTE shadowing by setting a flag.

Do you mean RWBF=1 in the CAP register? Given that "Newer hardware
implementations are expected to NOT require explicit software flushing
of write buffers and report RWBF=0 in the Capability register", we may
eventually run into guests that no longer check that flag if we expose
something that looks like a "newer" implementation.

However, this flag is not set right now in our VT-d model.


I'd like us to find some way to avoid possibility
of user error creating a configuration mixing e.g.
vfio with the amd iommu.

I'm not sure how to do this.

Any idea?

There is likely no way around write-protecting the IOMMU page tables (in
KVM mode) once we evaluated and cached them somewhere. For now, I would
simply deny vfio while an IOMMU is active on x86.

Should I implement this, in the meantime ?


Jan






Re: [Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-02 Thread David Kiarie
On Thu, Mar 3, 2016 at 12:17 AM, Michael S. Tsirkin  wrote:
> On Thu, Mar 03, 2016 at 12:09:28AM +0300, David Kiarie wrote:
>>
>>
>> On 22/02/16 14:22, Marcel Apfelbaum wrote:
>> >On 02/21/2016 08:11 PM, David Kiarie wrote:
>> >>Add AMD IOMMU emulation support to q35 chipset
>> >>
>> >>Signed-off-by: David Kiarie 
>> >>---
>> >>  hw/pci-host/piix.c|  1 +
>> >>  hw/pci-host/q35.c | 14 --
>> >>  include/hw/i386/intel_iommu.h |  1 +
>> >>  3 files changed, 14 insertions(+), 2 deletions(-)
>> >>
>> >>diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> >>index 41aa66f..ab2e24a 100644
>> >>--- a/hw/pci-host/piix.c
>> >>+++ b/hw/pci-host/piix.c
>> >>@@ -36,6 +36,7 @@
>> >>  #include "hw/i386/ioapic.h"
>> >>  #include "qapi/visitor.h"
>> >>  #include "qemu/error-report.h"
>> >>+#include "hw/i386/amd_iommu.h"
>> >
>> >Hi,
>> >
>> >I think you don't need this include anymore.
>> >
>> >>
>> >>  /*
>> >>   * I440FX chipset data sheet.
>> >>diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> >>index 115fb8c..355fb32 100644
>> >>--- a/hw/pci-host/q35.c
>> >>+++ b/hw/pci-host/q35.c
>> >>@@ -31,6 +31,7 @@
>> >>  #include "hw/hw.h"
>> >>  #include "hw/pci-host/q35.h"
>> >>  #include "qapi/visitor.h"
>> >>+#include "hw/i386/amd_iommu.h"
>> >>
>> >>/
>> >>   * Q35 host
>> >>@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>> >>   mch->pci_address_space, &mch->pam_regions[i+1],
>> >>   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>> >>  }
>> >>-/* Intel IOMMU (VT-d) */
>> >>-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> >>+
>> >>+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR)
>> >>== 0) {
>> >>+/* Intel IOMMU (VT-d) */
>> >>  mch_init_dmar(mch);
>> >>+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>> >>AMD_IOMMU_STR)
>> >>+   == 0) {
>> >>+AMDIOMMUState *iommu_state;
>> >>+PCIDevice *iommu;
>> >>+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> >>+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>
> Pls don't hardcode paths like this. Set addr property instead.
>
>> >>+iommu_state = AMD_IOMMU_DEVICE(iommu);
>> >>+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>> >
>> >pci_setup_iommu third parameter is void*, so you don't need to cast to
>> >AMDIOMMUState
>> >before passing it.
>>
>> This include is necessary for the definition of "AMD_IOMMU_STR" either way
>> so am leaving this as is.
>
> This option parsing is just too ugly.
>
> Looks like it was a mistake to support the iommu
> machine property, but I see no reason to add to the
> existing mess.
>
> Can't users create iommu with -device amd-iommu ?

You mean getting rid of the above code and starting device with
'-device amd-iommu' ? This way am not able to setup IOMMU regions for
devices correctly. IIRC 'pci_setup_iommu' when called from IOMMU code
sets up IOMMU region for IOMMU only. Calling this from the bus sets up
IOMMU regions for all devices though.

I need to setup IOMMU regions for all devices from the bus, to be able
to do that I need to have created the IOMMU device first.

>
> It's necessary if we are to support multiple IOMMUs, anyway.
>
>> >
>> >Thanks,
>> >Marcel
>> >
>> >>  }
>> >>  }
>> >>
>> >>diff --git a/include/hw/i386/intel_iommu.h
>> >>b/include/hw/i386/intel_iommu.h
>> >>index b024ffa..539530c 100644
>> >>--- a/include/hw/i386/intel_iommu.h
>> >>+++ b/include/hw/i386/intel_iommu.h
>> >>@@ -27,6 +27,7 @@
>> >>  #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
>> >>  #define INTEL_IOMMU_DEVICE(obj) \
>> >>   OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
>> >>+#define INTEL_IOMMU_STR "intel"
>> >>
>> >>  /* DMAR Hardware Unit Definition address (IOMMU unit) */
>> >>  #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
>> >>
>> >



Re: [Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-03 Thread David Kiarie
On Thu, Mar 3, 2016 at 12:49 PM, Michael S. Tsirkin  wrote:
> On Thu, Mar 03, 2016 at 01:04:31AM +0300, David Kiarie wrote:
>> On Thu, Mar 3, 2016 at 12:17 AM, Michael S. Tsirkin  wrote:
>> > On Thu, Mar 03, 2016 at 12:09:28AM +0300, David Kiarie wrote:
>> >>
>> >>
>> >> On 22/02/16 14:22, Marcel Apfelbaum wrote:
>> >> >On 02/21/2016 08:11 PM, David Kiarie wrote:
>> >> >>Add AMD IOMMU emulation support to q35 chipset
>> >> >>
>> >> >>Signed-off-by: David Kiarie 
>> >> >>---
>> >> >>  hw/pci-host/piix.c|  1 +
>> >> >>  hw/pci-host/q35.c | 14 --
>> >> >>  include/hw/i386/intel_iommu.h |  1 +
>> >> >>  3 files changed, 14 insertions(+), 2 deletions(-)
>> >> >>
>> >> >>diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> >> >>index 41aa66f..ab2e24a 100644
>> >> >>--- a/hw/pci-host/piix.c
>> >> >>+++ b/hw/pci-host/piix.c
>> >> >>@@ -36,6 +36,7 @@
>> >> >>  #include "hw/i386/ioapic.h"
>> >> >>  #include "qapi/visitor.h"
>> >> >>  #include "qemu/error-report.h"
>> >> >>+#include "hw/i386/amd_iommu.h"
>> >> >
>> >> >Hi,
>> >> >
>> >> >I think you don't need this include anymore.
>> >> >
>> >> >>
>> >> >>  /*
>> >> >>   * I440FX chipset data sheet.
>> >> >>diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> >> >>index 115fb8c..355fb32 100644
>> >> >>--- a/hw/pci-host/q35.c
>> >> >>+++ b/hw/pci-host/q35.c
>> >> >>@@ -31,6 +31,7 @@
>> >> >>  #include "hw/hw.h"
>> >> >>  #include "hw/pci-host/q35.h"
>> >> >>  #include "qapi/visitor.h"
>> >> >>+#include "hw/i386/amd_iommu.h"
>> >> >>
>> >> >>/
>> >> >>   * Q35 host
>> >> >>@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>> >> >>   mch->pci_address_space, &mch->pam_regions[i+1],
>> >> >>   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>> >> >>  }
>> >> >>-/* Intel IOMMU (VT-d) */
>> >> >>-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> >> >>+
>> >> >>+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR)
>> >> >>== 0) {
>> >> >>+/* Intel IOMMU (VT-d) */
>> >> >>  mch_init_dmar(mch);
>> >> >>+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>> >> >>AMD_IOMMU_STR)
>> >> >>+   == 0) {
>> >> >>+AMDIOMMUState *iommu_state;
>> >> >>+PCIDevice *iommu;
>> >> >>+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> >> >>+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> >
>> > Pls don't hardcode paths like this. Set addr property instead.
>> >
>> >> >>+iommu_state = AMD_IOMMU_DEVICE(iommu);
>> >> >>+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>> >> >
>> >> >pci_setup_iommu third parameter is void*, so you don't need to cast to
>> >> >AMDIOMMUState
>> >> >before passing it.
>> >>
>> >> This include is necessary for the definition of "AMD_IOMMU_STR" either way
>> >> so am leaving this as is.
>> >
>> > This option parsing is just too ugly.
>> >
>> > Looks like it was a mistake to support the iommu
>> > machine property, but I see no reason to add to the
>> > existing mess.
>> >
>> > Can't users create iommu with -device amd-iommu ?
>>
>> You mean getting rid of the above code and starting device with
>> '-device amd-iommu' ? This way am not able to setup IOMMU regions for
>> devices correctly. IIRC 'pci_setup_iommu' when called from IOMMU code
>> sets up IOMMU region for IOMMU only

Re: [Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-03 Thread David Kiarie
On Thu, Mar 3, 2016 at 3:06 PM, Marcel Apfelbaum  wrote:
> On 03/03/2016 02:02 PM, Marcel Apfelbaum wrote:
>>
>> On 03/03/2016 01:47 PM, David Kiarie wrote:
>>>
>>> On Thu, Mar 3, 2016 at 12:49 PM, Michael S. Tsirkin 
>>> wrote:
>>>>
>>>> On Thu, Mar 03, 2016 at 01:04:31AM +0300, David Kiarie wrote:
>>>>>
>>>>> On Thu, Mar 3, 2016 at 12:17 AM, Michael S. Tsirkin 
>>>>> wrote:
>>>>>>
>>>>>> On Thu, Mar 03, 2016 at 12:09:28AM +0300, David Kiarie wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 22/02/16 14:22, Marcel Apfelbaum wrote:
>>>>>>>>
>>>>>>>> On 02/21/2016 08:11 PM, David Kiarie wrote:
>>>>>>>>>
>>>>>>>>> Add AMD IOMMU emulation support to q35 chipset
>>>>>>>>>
>>>>>>>>> Signed-off-by: David Kiarie 
>>>>>>>>> ---
>>>>>>>>>   hw/pci-host/piix.c|  1 +
>>>>>>>>>   hw/pci-host/q35.c | 14 --
>>>>>>>>>   include/hw/i386/intel_iommu.h |  1 +
>>>>>>>>>   3 files changed, 14 insertions(+), 2 deletions(-)
>>>>>>>>>
>>>>>>>>> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>>>>>>>>> index 41aa66f..ab2e24a 100644
>>>>>>>>> --- a/hw/pci-host/piix.c
>>>>>>>>> +++ b/hw/pci-host/piix.c
>>>>>>>>> @@ -36,6 +36,7 @@
>>>>>>>>>   #include "hw/i386/ioapic.h"
>>>>>>>>>   #include "qapi/visitor.h"
>>>>>>>>>   #include "qemu/error-report.h"
>>>>>>>>> +#include "hw/i386/amd_iommu.h"
>>>>>>>>
>>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I think you don't need this include anymore.
>>>>>>>>
>>>>>>>>>
>>>>>>>>>   /*
>>>>>>>>>* I440FX chipset data sheet.
>>>>>>>>> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>>>>>>>>> index 115fb8c..355fb32 100644
>>>>>>>>> --- a/hw/pci-host/q35.c
>>>>>>>>> +++ b/hw/pci-host/q35.c
>>>>>>>>> @@ -31,6 +31,7 @@
>>>>>>>>>   #include "hw/hw.h"
>>>>>>>>>   #include "hw/pci-host/q35.h"
>>>>>>>>>   #include "qapi/visitor.h"
>>>>>>>>> +#include "hw/i386/amd_iommu.h"
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> /
>>>>>>>>>* Q35 host
>>>>>>>>> @@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error
>>>>>>>>> **errp)
>>>>>>>>>mch->pci_address_space, &mch->pam_regions[i+1],
>>>>>>>>>PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE,
>>>>>>>>> PAM_EXPAN_SIZE);
>>>>>>>>>   }
>>>>>>>>> -/* Intel IOMMU (VT-d) */
>>>>>>>>> -if (object_property_get_bool(qdev_get_machine(), "iommu",
>>>>>>>>> NULL)) {
>>>>>>>>> +
>>>>>>>>> +if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>>>>>>>>> INTEL_IOMMU_STR)
>>>>>>>>> == 0) {
>>>>>>>>> +/* Intel IOMMU (VT-d) */
>>>>>>>>>   mch_init_dmar(mch);
>>>>>>>>> +} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>>>>>>>>> AMD_IOMMU_STR)
>>>>>>>>> +   == 0) {
>>>>>>>>> +AMDIOMMUState *iommu_state;
>>>>>>>>> +PCIDevice *iommu;
>>>>>>>>> +PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>>>>>>>>> +iommu = pci_create_simple

Re: [Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-08 Thread David Kiarie
On Thu, Mar 3, 2016 at 12:49 PM, Michael S. Tsirkin  wrote:
> On Thu, Mar 03, 2016 at 01:04:31AM +0300, David Kiarie wrote:
>> On Thu, Mar 3, 2016 at 12:17 AM, Michael S. Tsirkin  wrote:
>> > On Thu, Mar 03, 2016 at 12:09:28AM +0300, David Kiarie wrote:
>> >>
>> >>
>> >> On 22/02/16 14:22, Marcel Apfelbaum wrote:
>> >> >On 02/21/2016 08:11 PM, David Kiarie wrote:
>> >> >>Add AMD IOMMU emulation support to q35 chipset
>> >> >>
>> >> >>Signed-off-by: David Kiarie 
>> >> >>---
>> >> >>  hw/pci-host/piix.c|  1 +
>> >> >>  hw/pci-host/q35.c | 14 --
>> >> >>  include/hw/i386/intel_iommu.h |  1 +
>> >> >>  3 files changed, 14 insertions(+), 2 deletions(-)
>> >> >>
>> >> >>diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> >> >>index 41aa66f..ab2e24a 100644
>> >> >>--- a/hw/pci-host/piix.c
>> >> >>+++ b/hw/pci-host/piix.c
>> >> >>@@ -36,6 +36,7 @@
>> >> >>  #include "hw/i386/ioapic.h"
>> >> >>  #include "qapi/visitor.h"
>> >> >>  #include "qemu/error-report.h"
>> >> >>+#include "hw/i386/amd_iommu.h"
>> >> >
>> >> >Hi,
>> >> >
>> >> >I think you don't need this include anymore.
>> >> >
>> >> >>
>> >> >>  /*
>> >> >>   * I440FX chipset data sheet.
>> >> >>diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> >> >>index 115fb8c..355fb32 100644
>> >> >>--- a/hw/pci-host/q35.c
>> >> >>+++ b/hw/pci-host/q35.c
>> >> >>@@ -31,6 +31,7 @@
>> >> >>  #include "hw/hw.h"
>> >> >>  #include "hw/pci-host/q35.h"
>> >> >>  #include "qapi/visitor.h"
>> >> >>+#include "hw/i386/amd_iommu.h"
>> >> >>
>> >> >>/
>> >> >>   * Q35 host
>> >> >>@@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>> >> >>   mch->pci_address_space, &mch->pam_regions[i+1],
>> >> >>   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>> >> >>  }
>> >> >>-/* Intel IOMMU (VT-d) */
>> >> >>-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> >> >>+
>> >> >>+if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR)
>> >> >>== 0) {
>> >> >>+/* Intel IOMMU (VT-d) */
>> >> >>  mch_init_dmar(mch);
>> >> >>+} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu,
>> >> >>AMD_IOMMU_STR)
>> >> >>+   == 0) {
>> >> >>+AMDIOMMUState *iommu_state;
>> >> >>+PCIDevice *iommu;
>> >> >>+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> >> >>+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>> >
>> > Pls don't hardcode paths like this. Set addr property instead.
>> >
>> >> >>+iommu_state = AMD_IOMMU_DEVICE(iommu);
>> >> >>+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>> >> >
>> >> >pci_setup_iommu third parameter is void*, so you don't need to cast to
>> >> >AMDIOMMUState
>> >> >before passing it.
>> >>
>> >> This include is necessary for the definition of "AMD_IOMMU_STR" either way
>> >> so am leaving this as is.
>> >
>> > This option parsing is just too ugly.
>> >
>> > Looks like it was a mistake to support the iommu
>> > machine property, but I see no reason to add to the
>> > existing mess.
>> >
>> > Can't users create iommu with -device amd-iommu ?
>>
>> You mean getting rid of the above code and starting device with
>> '-device amd-iommu' ? This way am not able to setup IOMMU regions for
>> devices correctly. IIRC 'pci_setup_iommu' when called from IOMMU code
>> sets up IOMMU region for IOMMU onl

Re: [Qemu-devel] [V6 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-12 Thread David Kiarie
On Fri, Mar 11, 2016 at 4:22 PM, Michael S. Tsirkin  wrote:
> On Sun, Feb 21, 2016 at 09:11:00PM +0300, David Kiarie wrote:
>> Add AMD IOMMU emulation support to q35 chipset
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/pci-host/piix.c|  1 +
>>  hw/pci-host/q35.c | 14 --
>>  include/hw/i386/intel_iommu.h |  1 +
>>  3 files changed, 14 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
>> index 41aa66f..ab2e24a 100644
>> --- a/hw/pci-host/piix.c
>> +++ b/hw/pci-host/piix.c
>> @@ -36,6 +36,7 @@
>>  #include "hw/i386/ioapic.h"
>>  #include "qapi/visitor.h"
>>  #include "qemu/error-report.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>  /*
>>   * I440FX chipset data sheet.
>
> Why is this needed?
>
>> diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
>> index 115fb8c..355fb32 100644
>> --- a/hw/pci-host/q35.c
>> +++ b/hw/pci-host/q35.c
>> @@ -31,6 +31,7 @@
>>  #include "hw/hw.h"
>>  #include "hw/pci-host/q35.h"
>>  #include "qapi/visitor.h"
>> +#include "hw/i386/amd_iommu.h"
>>
>>  
>> /
>>   * Q35 host
>> @@ -505,9 +506,18 @@ static void mch_realize(PCIDevice *d, Error **errp)
>>   mch->pci_address_space, &mch->pam_regions[i+1],
>>   PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
>>  }
>> -/* Intel IOMMU (VT-d) */
>> -if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
>> +
>> +if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, INTEL_IOMMU_STR) == 
>> 0) {
>> +/* Intel IOMMU (VT-d) */
>>  mch_init_dmar(mch);
>> +} else if (g_strcmp0(MACHINE(qdev_get_machine())->iommu, AMD_IOMMU_STR)
>> +   == 0) {
>> +AMDIOMMUState *iommu_state;
>> +PCIDevice *iommu;
>> +PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
>> +iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
>
> address can be set through a property.

I missed something here, what is the problem ?Is it the hardcoded address ?

>
>> +iommu_state = AMD_IOMMU_DEVICE(iommu);
>> +pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
>
>
> It would be better to move this chunk to a separate function.
>
>>  }
>>  }
>>
>> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
>> index b024ffa..539530c 100644
>> --- a/include/hw/i386/intel_iommu.h
>> +++ b/include/hw/i386/intel_iommu.h
>> @@ -27,6 +27,7 @@
>>  #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
>>  #define INTEL_IOMMU_DEVICE(obj) \
>>   OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
>> +#define INTEL_IOMMU_STR "intel"
>>
>>  /* DMAR Hardware Unit Definition address (IOMMU unit) */
>>  #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
>> --
>> 2.1.4



[Qemu-devel] [V7 0/4] AMD IOMMU

2016-03-13 Thread David Kiarie
Hello there,

This series adds AMD IOMMU emulation support to Qemu.

The only main change since V6 is:
  -Fixed a cache bug that caused the issue reported by Jan

I have assummed that we are running one IOMMU and users don't have the freedom 
to run many IOMMUs. For instance, I've decided to stick with 
'pci_create_simple' since if I change this and manually create the the device 
inorder to set the addr, I'll be repeating exactly what 'pci_create_simple' 
does while there is no immediate benefit. Being able to run multiple IOMMUs is 
a plus but at the moment I experience a few problems with the code while there 
is no immediate benefit.

Other than these patches there's also an planned GSoC project to add features 
to feature-limited AMD IO MMU listed here[1]. It could also look at the the 
possibility of running multiple IOMMUs. GSoC is a program that offers students 
stipends to work on open source projects. You can read more about GSoC here[2]. 
Am a student and am willing to take up this IO MMU related project but I've not 
got a full mentor. Yeah, you're right, there are mentors listed on the 
project's details but they would only want to co-mentor as they may not have 
much time. They were listed there mainly for purposes of listing the project. 
I'd like to know if anyone is willing to mentor this project mainly the people 
involved in the review process or anyone else! 

David Kiarie (4):
  hw/i386: Introduce AMD IOMMU
  hw/i386: ACPI table for AMD IOMMU
  hw/core: Add AMD IOMMU to machine properties
  hw/pci-host: Emulate AMD IOMMU

 hw/core/machine.c |   27 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |   98 ++-
 hw/i386/amd_iommu.c   | 1431 +
 hw/i386/amd_iommu.h   |  398 
 hw/pci-host/q35.c |   21 +-
 include/hw/acpi/acpi-defs.h   |   55 ++
 include/hw/boards.h   |1 +
 include/hw/i386/intel_iommu.h |2 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |7 +-
 util/qemu-config.c|4 +-
 12 files changed, 2027 insertions(+), 20 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

[1]http://qemu-project.org/Google_Summer_of_Code_2016#Qemu_AMD_IO_MMU_emulation
[2]https://summerofcode.withgoogle.com/
-- 
2.1.4




[Qemu-devel] [V7 3/4] hw/core: Add AMD IOMMU to machine properties

2016-03-13 Thread David Kiarie
Add IOMMU as a string to machine properties which is
used to control whether and the type of IOMMU to emulate

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 27 ---
 include/hw/boards.h |  1 +
 qemu-options.hx |  7 +--
 util/qemu-config.c  |  4 ++--
 4 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index a8c4680..ce23b3d 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -14,6 +14,8 @@
 #include "hw/boards.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -298,6 +300,20 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static bool machine_get_amd_iommu_override(Object *obj, Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+
+return ms->amd_iommu_type;
+}
+
+static void machine_set_amd_iommu_override(Object *obj, bool value, Error 
**errp)
+{
+MachineState *ms = MACHINE(obj);
+
+ms->amd_iommu_type = value;
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -471,10 +487,15 @@ static void machine_initfn(Object *obj)
 "Firmware image",
 NULL);
 object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"Set on to enable IOMMU emulation",
+NULL);
+object_property_add_bool(obj, "amd-iommu",
+machine_get_amd_iommu_override,
+machine_set_amd_iommu_override, NULL);
+object_property_set_description(obj, "amd-iommu",
+"Set on to override emulated IOMMU to AMD 
IOMMU",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index b5d7eae..5bdd0bb 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -126,6 +126,7 @@ struct MachineState {
 bool igd_gfx_passthru;
 char *firmware;
 bool iommu;
+bool amd_iommu_type;
 bool suppress_vmdesc;
 bool enforce_config_section;
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 0cf7bb9..de3f02e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=on|off controls emulated IOMMU support(default: 
off)\n"
+"amd-iommu=on|off overrides emulated IOMMU to AMD IOMMU 
(default: off)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -74,7 +75,9 @@ Enables or disables memory merge support. This feature, when 
supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
 @item iommu=on|off
-Enables or disables emulated Intel IOMMU (VT-d) support. The default is off.
+Enables and disables IOMMU emulation. The default is off.
+@item amd-iommu=on|off
+Overrides emulated IOMMU from AMD IOMMU. By default Intel IOMMU is emulated.
 @item aes-key-wrap=on|off
 Enables or disables AES key wrapping support on s390-ccw hosts. This feature
 controls whether AES wrapping keys will be created to allow
diff --git a/util/qemu-config.c b/util/qemu-config.c
index fb97307..f1b5a3b 100644
--- a/util/qemu-config.c
+++ b/util/qemu-config.c
@@ -213,8 +213,8 @@ static QemuOptsList machine_opts = {
 .help = "firmware image",
 },{
 .name = "iommu",
-.type = QEMU_OPT_BOOL,
-.help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
+.type =  QEMU_OPT_STRING,
+.help = "Enables IOMMU and sets the emulated type",
 },{
 .name = "suppress-vmdesc",
 .type = QEMU_OPT_BOOL,
-- 
2.1.4




[Qemu-devel] [V7 4/4] hw/pci-host: Emulate AMD IOMMU

2016-03-13 Thread David Kiarie
Add AMD IOMMU emulation support to q35 chipset

Signed-off-by: David Kiarie 
---
 hw/pci-host/q35.c | 21 +++--
 include/hw/i386/intel_iommu.h |  1 +
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 115fb8c..5f6298e 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -31,6 +31,7 @@
 #include "hw/hw.h"
 #include "hw/pci-host/q35.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -447,6 +448,19 @@ static void mch_init_dmar(MCHPCIState *mch)
 pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
 }
 
+static void mch_init_amdvi(MCHPCIState *mch)
+{
+AMDIOMMUState *iommu_state;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+PCIDevice *iommu;
+
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
+}
+
 static void mch_realize(PCIDevice *d, Error **errp)
 {
 int i;
@@ -505,8 +519,11 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (object_property_get_bool(qdev_get_machine(), "iommu", NULL) &&
+object_property_get_bool(qdev_get_machine(), "amd-iommu", NULL)) {
+mch_init_amdvi(mch);
+} else if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
 mch_init_dmar(mch);
 }
 }
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7e511e1..5a520f3 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -28,6 +28,7 @@
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
-- 
2.1.4




[Qemu-devel] [V7 2/4] hw/i386: ACPI table for AMD IOMMU

2016-03-13 Thread David Kiarie
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU

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

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b888008..f6ab533 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)
 {
@@ -2542,6 +2549,78 @@ 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, &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, 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 GArray *
 build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
 {
@@ -2600,16 +2679,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());
@@ -2630,6 +2699,7 @@ void acpi_build(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;
 AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
@@ -2696,7 +2766,13 @@ void acpi_build(AcpiBuildTables *tables)
 acpi_add_table(table_offsets, tables_blob);
 build_mcfg_q3

[Qemu-devel] [V7 1/4] hw/i386: Introduce AMD IOMMU

2016-03-13 Thread David Kiarie
Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
mininal IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1431 +
 hw/i386/amd_iommu.h   |  398 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1832 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..ff967b3
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1431 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU, DEBUG_CUSTOM
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(CUSTOM);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+#define ENCODE_EVENT(devid, info, addr, rshift) do { \
+*(uint16_t *)&evt[0] = devid; \
+*(uint8_t *)&evt[3]  = info;  \
+*(uint64_t *)&evt[4] = rshift ? cpu_to_le64(addr):\
+   cpu_to_le64(addr) >> rshift; \
+} while (0)
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(&s->mmior[

Re: [Qemu-devel] [V7 3/4] hw/core: Add AMD IOMMU to machine properties

2016-03-14 Thread David Kiarie
On Mon, Mar 14, 2016 at 11:40 AM, Marcel Apfelbaum  wrote:
> On 03/14/2016 02:24 AM, David Kiarie wrote:
>>
>> Add IOMMU as a string to machine properties which is
>> used to control whether and the type of IOMMU to emulate
>>
>> Signed-off-by: David Kiarie 
>> ---
>>   hw/core/machine.c   | 27 ---
>>   include/hw/boards.h |  1 +
>>   qemu-options.hx |  7 +--
>>   util/qemu-config.c  |  4 ++--
>>   4 files changed, 32 insertions(+), 7 deletions(-)
>>
>> diff --git a/hw/core/machine.c b/hw/core/machine.c
>> index a8c4680..ce23b3d 100644
>> --- a/hw/core/machine.c
>> +++ b/hw/core/machine.c
>> @@ -14,6 +14,8 @@
>>   #include "hw/boards.h"
>>   #include "qapi-visit.h"
>>   #include "qapi/visitor.h"
>> +#include "hw/i386/amd_iommu.h"
>> +#include "hw/i386/intel_iommu.h"
>>   #include "hw/sysbus.h"
>>   #include "sysemu/sysemu.h"
>>   #include "qemu/error-report.h"
>> @@ -298,6 +300,20 @@ static void machine_set_iommu(Object *obj, bool
>> value, Error **errp)
>>   ms->iommu = value;
>>   }
>>
>> +static bool machine_get_amd_iommu_override(Object *obj, Error **errp)
>> +{
>> +MachineState *ms = MACHINE(obj);
>> +
>> +return ms->amd_iommu_type;
>> +}
>> +
>> +static void machine_set_amd_iommu_override(Object *obj, bool value, Error
>> **errp)
>> +{
>> +MachineState *ms = MACHINE(obj);
>> +
>> +ms->amd_iommu_type = value;
>> +}
>> +
>>   static void machine_set_suppress_vmdesc(Object *obj, bool value, Error
>> **errp)
>>   {
>>   MachineState *ms = MACHINE(obj);
>> @@ -471,10 +487,15 @@ static void machine_initfn(Object *obj)
>>   "Firmware image",
>>   NULL);
>>   object_property_add_bool(obj, "iommu",
>> - machine_get_iommu,
>> - machine_set_iommu, NULL);
>> +machine_get_iommu, machine_set_iommu, NULL);
>>   object_property_set_description(obj, "iommu",
>> -"Set on/off to enable/disable Intel
>> IOMMU (VT-d)",
>> +"Set on to enable IOMMU emulation",
>> +NULL);
>> +object_property_add_bool(obj, "amd-iommu",
>> +machine_get_amd_iommu_override,
>> +machine_set_amd_iommu_override, NULL);
>> +object_property_set_description(obj, "amd-iommu",
>> +"Set on to override emulated IOMMU to
>> AMD IOMMU",
>>   NULL);
>>   object_property_add_bool(obj, "suppress-vmdesc",
>>machine_get_suppress_vmdesc,
>> diff --git a/include/hw/boards.h b/include/hw/boards.h
>> index b5d7eae..5bdd0bb 100644
>> --- a/include/hw/boards.h
>> +++ b/include/hw/boards.h
>> @@ -126,6 +126,7 @@ struct MachineState {
>>   bool igd_gfx_passthru;
>>   char *firmware;
>>   bool iommu;
>> +bool amd_iommu_type;
>>   bool suppress_vmdesc;
>>   bool enforce_config_section;
>>
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 0cf7bb9..de3f02e 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
>>   "kvm_shadow_mem=size of KVM shadow MMU\n"
>>   "dump-guest-core=on|off include guest memory in a
>> core dump (default=on)\n"
>>   "mem-merge=on|off controls memory merge support
>> (default: on)\n"
>> -"iommu=on|off controls emulated Intel IOMMU (VT-d)
>> support (default=off)\n"
>> +"iommu=on|off controls emulated IOMMU
>> support(default: off)\n"
>> +"amd-iommu=on|off overrides emulated IOMMU to AMD
>> IOMMU (default: off)\n"
>
>
> Hi David,
>
> I think this is a step backward from the last series (in my opinion).
> Summarizing what Jan and Michael said, it should be:
>   iommu=on|off controls emulated IOMMU support(default: off)
>   x-iommu-type=intel|amd controls the IOMMU emulation type(default:

[Qemu-devel] [V8 0/4] AMD IOMMU

2016-04-01 Thread David Kiarie
Hello all, 

Long time no see, at usual ;)

AMD IOMMU patches fixing a few issues mentioned in previous version, formatting
errors and commit messages

David Kiarie (4):
  hw/i386: Introduce AMD IOMMU
  hw/i386: ACPI table for AMD IOMMU
  hw/core: Add AMD IOMMU to machine properties
  hw/pci-host: Emulate AMD IOMMU

 hw/core/machine.c |   32 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |   98 ++-
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 
 hw/pci-host/q35.c |   21 +-
 include/hw/acpi/acpi-defs.h   |   55 ++
 include/hw/boards.h   |1 +
 include/hw/i386/intel_iommu.h |2 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |7 +-
 util/qemu-config.c|8 +-
 12 files changed, 2031 insertions(+), 20 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [V8 4/4] hw/pci-host: Emulate AMD IOMMU

2016-04-01 Thread David Kiarie
Add AMD IOMMU emulation support to q35 chipset

Signed-off-by: David Kiarie 
---
 hw/pci-host/q35.c | 21 +++--
 include/hw/i386/intel_iommu.h |  1 +
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 70f897e..37f8a84 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -32,6 +32,7 @@
 #include "hw/pci-host/q35.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -448,6 +449,19 @@ static void mch_init_dmar(MCHPCIState *mch)
 pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
 }
 
+static void mch_init_amdvi(MCHPCIState *mch)
+{
+AMDIOMMUState *iommu_state;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+PCIDevice *iommu;
+
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
+}
+
 static void mch_realize(PCIDevice *d, Error **errp)
 {
 int i;
@@ -506,8 +520,11 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (object_property_get_bool(qdev_get_machine(), "iommu", NULL) &&
+MACHINE(qdev_get_machine())->x_iommu_type) {
+mch_init_amdvi(mch);
+} else if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
 mch_init_dmar(mch);
 }
 }
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7e511e1..5a520f3 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -28,6 +28,7 @@
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
-- 
2.1.4




[Qemu-devel] [V8 2/4] hw/i386: ACPI table for AMD IOMMU

2016-04-01 Thread David Kiarie
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU

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

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 35180ef..a54a22c 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"
@@ -118,6 +119,12 @@ typedef struct AcpiBuildPciBusHotplugState {
 bool pcihp_bridge_en;
 } AcpiBuildPciBusHotplugState;
 
+typedef enum iommu_type {
+TYPE_AMD,
+TYPE_INTEL,
+TYPE_NONE
+} iommu_type;
+
 static void acpi_get_pm_info(AcpiPmInfo *pm)
 {
 Object *piix = piix4_pm_find();
@@ -2588,6 +2595,78 @@ 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, &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, 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 GArray *
 build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
 {
@@ -2646,16 +2725,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
 void acpi_build(AcpiBuildTables *tables, MachineState *machine)
 {
@@ -2668,6 +2737,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 AcpiMcfgInfo mcfg;
 PcPciInfo pci;
 uint8_t *u;
+iommu_type type = has_iommu();
 size_t aml_len = 0;
 GArray *tables_blob = tables->table_data;
 AcpiSlicOem slic_oem = { .id = NULL, .table_id = NULL };
@@ -2733,7 +2803,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState 
*machine)
 acpi_add_table(tabl

[Qemu-devel] [V8 1/4] hw/i386: Introduce AMD IOMMU

2016-04-01 Thread David Kiarie
Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
minimal IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1827 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..66dbeb3
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1426 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU, DEBUG_CUSTOM
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(CUSTOM);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+#define ENCODE_EVENT(devid, info, addr, rshift) do { \
+*(uint16_t *)&evt[0] = devid; \
+*(uint8_t *)&evt[3]  = info;  \
+*(uint64_t *)&evt[4] = rshift ? cpu_to_le64(addr) :\
+   cpu_to_le64(addr) >> rshift; \
+} while (0)
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(

[Qemu-devel] [V8 3/4] hw/core: Add AMD IOMMU to machine properties

2016-04-01 Thread David Kiarie
Added a bool, subject to review to machine properties which
it used to override iommu emulated from Intel to AMD.

Signed-off-by: David Kiarie 
---
 hw/core/machine.c   | 32 +---
 include/hw/boards.h |  1 +
 qemu-options.hx |  7 +--
 util/qemu-config.c  |  8 ++--
 4 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 6dbbc85..792641b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -15,6 +15,8 @@
 #include "qapi/error.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -300,6 +302,26 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static void machine_set_iommu_override(Object *obj, const char *value,
+   Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+Error *err = NULL;
+
+ms->x_iommu_type = false;
+/* ensure a valid iommu type */
+if (g_strcmp0(value, AMD_IOMMU_STR) &&
+g_strcmp0(value, INTEL_IOMMU_STR)) {
+error_setg(errp, "Invalid IOMMU type %s", value);
+error_propagate(errp, err);
+return;
+}
+
+if ((g_strcmp0(value, AMD_IOMMU_STR) == 0)) {
+ms->x_iommu_type = true;
+}
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -473,10 +495,14 @@ static void machine_initfn(Object *obj)
 "Firmware image",
 NULL);
 object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+ machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"Set on to enable IOMMU emulation",
+NULL);
+object_property_add_str(obj, "x-iommu-type",
+NULL, machine_set_iommu_override, NULL);
+object_property_set_description(obj, "x-iommu-type",
+"Set on to override emulated IOMMU to AMD 
IOMMU",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index aad5f2a..07788fc 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -151,6 +151,7 @@ struct MachineState {
 bool igd_gfx_passthru;
 char *firmware;
 bool iommu;
+bool x_iommu_type;
 bool suppress_vmdesc;
 bool enforce_config_section;
 
diff --git a/qemu-options.hx b/qemu-options.hx
index a770086..14d30b7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=on|off controls emulated IOMMU support(default: 
off)\n"
+"x-iommu-type=amd|intel overrides emulated IOMMU to AMD 
IOMMU (default: intel)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -74,7 +75,9 @@ Enables or disables memory merge support. This feature, when 
supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
 @item iommu=on|off
-Enables or disables emulated Intel IOMMU (VT-d) support. The default is off.
+Enables and disables IOMMU emulation. The default is off.
+@item x-iommu-type=on|off
+Overrides emulated IOMMU from AMD IOMMU. By default Intel IOMMU is emulated.
 @item aes-key-wrap=on|off
 Enables or disables AES key wrapping support on s390-ccw hosts. This feature
 controls whether AES wrapping keys will be created to allow
diff --git a/util/qemu-config.c b/util/qemu-config.c
index fb97307..8886abf 100644
--- a/util/qemu-config.c
+++ b/util/

[Qemu-devel] [V9 0/4] AMD IOMMU

2016-04-24 Thread David Kiarie
Hi all, 

The current AMD IOMMU patches that fixes Igor's comments. I got rid of structs 
and instead 
added individual integer fields into the table data directly, as suggested.

I have also got rid of some un-used macros and fixed a few other miscellaneous 
things.

David Kiarie (4):
  hw/i386: Introduce AMD IOMMU
  hw/i386: ACPI table for AMD IOMMU
  hw/core: Add AMD IOMMU to machine properties
  hw/pci-host: Emulate AMD IOMMU

 hw/acpi/aml-build.c   |2 +-
 hw/acpi/core.c|   13 -
 hw/core/machine.c |   32 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |  101 ++-
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 
 hw/pci-host/q35.c |   21 +-
 include/hw/acpi/acpi-defs.h   |   14 +
 include/hw/acpi/acpi.h|   16 +
 include/hw/acpi/aml-build.h   |1 +
 include/hw/boards.h   |1 +
 include/hw/i386/intel_iommu.h |1 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |7 +-
 util/qemu-config.c|8 +-
 16 files changed, 2010 insertions(+), 34 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [V9 3/4] hw/core: Add AMD IOMMU to machine properties

2016-04-24 Thread David Kiarie
Added a bool, subject to review to machine properties which
it used to override iommu emulated from Intel to AMD.

Signed-off-by: David Kiarie 
---
 hw/core/machine.c | 32 +---
 include/hw/boards.h   |  1 +
 include/hw/i386/intel_iommu.h |  1 +
 qemu-options.hx   |  7 +--
 util/qemu-config.c|  8 ++--
 5 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 6dbbc85..792641b 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -15,6 +15,8 @@
 #include "qapi/error.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -300,6 +302,26 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static void machine_set_iommu_override(Object *obj, const char *value,
+   Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+Error *err = NULL;
+
+ms->x_iommu_type = false;
+/* ensure a valid iommu type */
+if (g_strcmp0(value, AMD_IOMMU_STR) &&
+g_strcmp0(value, INTEL_IOMMU_STR)) {
+error_setg(errp, "Invalid IOMMU type %s", value);
+error_propagate(errp, err);
+return;
+}
+
+if ((g_strcmp0(value, AMD_IOMMU_STR) == 0)) {
+ms->x_iommu_type = true;
+}
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -473,10 +495,14 @@ static void machine_initfn(Object *obj)
 "Firmware image",
 NULL);
 object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+ machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"Set on to enable IOMMU emulation",
+NULL);
+object_property_add_str(obj, "x-iommu-type",
+NULL, machine_set_iommu_override, NULL);
+object_property_set_description(obj, "x-iommu-type",
+"Set on to override emulated IOMMU to AMD 
IOMMU",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 8d4fe56..5a12a1c 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -152,6 +152,7 @@ struct MachineState {
 bool igd_gfx_passthru;
 char *firmware;
 bool iommu;
+bool x_iommu_type;
 bool suppress_vmdesc;
 bool enforce_config_section;
 
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index b024ffa..7e511e1 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -24,6 +24,7 @@
 #include "hw/qdev.h"
 #include "sysemu/dma.h"
 
+#define INTEL_IOMMU_STR "intel"
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
diff --git a/qemu-options.hx b/qemu-options.hx
index 6106520..81217d3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=on|off controls emulated IOMMU support(default: 
off)\n"
+"x-iommu-type=amd|intel overrides emulated IOMMU to AMD 
IOMMU (default: intel)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -74,7 +75,9 @@ Enables or disables memory merge support. This feature, when 
supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled by default).
 @item iommu=on

[Qemu-devel] [V9 2/4] hw/i386: ACPI table for AMD IOMMU

2016-04-24 Thread David Kiarie
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU

Signed-off-by: David Kiarie 
---
 hw/acpi/aml-build.c |   2 +-
 hw/acpi/core.c  |  13 --
 hw/i386/acpi-build.c| 101 +++-
 include/hw/acpi/acpi-defs.h |  14 ++
 include/hw/acpi/acpi.h  |  16 +++
 include/hw/acpi/aml-build.h |   1 +
 6 files changed, 122 insertions(+), 25 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ab89ca6..da11bf8 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -227,7 +227,7 @@ static void build_extop_package(GArray *package, uint8_t op)
 build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
 }
 
-static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+void build_append_int_noprefix(GArray *table, uint64_t value, int size)
 {
 int i;
 
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 7925a1a..ee0e687 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -29,19 +29,6 @@
 #include "qapi-visit.h"
 #include "qapi-event.h"
 
-struct acpi_table_header {
-uint16_t _length; /* our length, not actual part of the hdr */
-  /* allows easier parsing for fw_cfg clients */
-char sig[4];  /* ACPI signature (4 ASCII characters) */
-uint32_t length;  /* Length of table, in bytes, including header */
-uint8_t revision; /* ACPI Specification minor version # */
-uint8_t checksum; /* To make sum of entire table == 0 */
-char oem_id[6];   /* OEM identification */
-char oem_table_id[8]; /* OEM table identification */
-uint32_t oem_revision;/* OEM revision number */
-char asl_compiler_id[4];  /* ASL compiler vendor ID */
-uint32_t asl_compiler_revision; /* ASL compiler revision number */
-} QEMU_PACKED;
 
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6477003..19efc68 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"
@@ -118,6 +119,12 @@ typedef struct AcpiBuildPciBusHotplugState {
 bool pcihp_bridge_en;
 } AcpiBuildPciBusHotplugState;
 
+typedef enum IommuType {
+TYPE_AMD,
+TYPE_INTEL,
+TYPE_NONE
+} IommuType;
+
 static void acpi_get_pm_info(AcpiPmInfo *pm)
 {
 Object *piix = piix4_pm_find();
@@ -2598,6 +2605,81 @@ build_dmar_q35(GArray *table_data, GArray *linker)
  "DMAR", table_data->len - dmar_start, 1, NULL, NULL);
 }
 
+#define IOMMU_IVRS_LENGTH 0x30
+/* increase ivdb length if more devices are added */
+#define IOMMU_IVDB_LENGTH 0x20
+
+static void
+build_amd_iommu(GArray *table_data, GArray *linker)
+{
+int iommu_start = table_data->len;
+bool iommu_ambig;
+
+/* IVRS definition  - table header has an extra 2-byte field */
+acpi_data_push(table_data, (sizeof(acpi_table_header) - 2));
+/* common virtualization information */
+build_append_int_noprefix(table_data, AMD_IOMMU_HOST_ADDRESS_WIDTH << 8, 
4);
+/* reserved */
+build_append_int_noprefix(table_data, 0, 8);
+
+AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("",
+TYPE_AMD_IOMMU_DEVICE, &iommu_ambig);
+
+/* IVDB definition - type 10h */
+if (!iommu_ambig) {
+/* IVHD definition - type 10h */
+build_append_int_noprefix(table_data, 0x10, 1);
+/* virtualization flags */
+build_append_int_noprefix(table_data, (IVHD_HT_TUNEN |
+ IVHD_PPRSUP | IVHD_IOTLBSUP | IVHD_PREFSUP), 1);
+/* ivhd length */
+build_append_int_noprefix(table_data, IOMMU_IVDB_LENGTH, 2);
+/* iommu device id */
+build_append_int_noprefix(table_data, PCI_DEVICE_ID_RD890_IOMMU, 2);
+/* offset of capability registers */
+build_append_int_noprefix(table_data, s->capab_offset, 2);
+/* mmio base register */
+build_append_int_noprefix(table_data, s->mmio.addr, 8);
+/* pci segment */
+build_append_int_noprefix(table_data, 0, 2);
+/* interrupt numbers */
+build_append_int_noprefix(table_data, 0, 2);
+/* feature reporting */
+build_append_int_noprefix(table_data, (IVHD_EFR_GTSUP |
+IVHD_EFR_HATS | IVHD_EFR_GATS), 4);
+/* 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
+ *

[Qemu-devel] [V9 1/4] hw/i386: Introduce AMD IOMMU

2016-04-24 Thread David Kiarie
Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
minimal IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1827 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..96ed8c3
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1426 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/amd_iommu.h"
+
+/*#define DEBUG_AMD_IOMMU*/
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU, DEBUG_CUSTOM
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(CUSTOM);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+#define ENCODE_EVENT(devid, info, addr, rshift) do { \
+*(uint16_t *)&evt[0] = devid; \
+*(uint8_t *)&evt[3]  = info;  \
+*(uint64_t *)&evt[4] = rshift ? cpu_to_le64(addr) :\
+   cpu_to_le64(addr) >> rshift; \
+} while (0)
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_le_p(

[Qemu-devel] [V9 4/4] hw/pci-host: Emulate AMD IOMMU

2016-04-24 Thread David Kiarie
Add AMD IOMMU emulation support to q35 chipset

Signed-off-by: David Kiarie 
---
 hw/pci-host/q35.c | 21 +++--
 include/hw/i386/intel_iommu.h |  2 +-
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index 70f897e..37f8a84 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -32,6 +32,7 @@
 #include "hw/pci-host/q35.h"
 #include "qapi/error.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
 
 /
  * Q35 host
@@ -448,6 +449,19 @@ static void mch_init_dmar(MCHPCIState *mch)
 pci_setup_iommu(pci_bus, q35_host_dma_iommu, mch->iommu);
 }
 
+static void mch_init_amdvi(MCHPCIState *mch)
+{
+AMDIOMMUState *iommu_state;
+PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(mch)));
+PCIDevice *iommu;
+
+iommu = pci_create_simple(bus, 0x20, TYPE_AMD_IOMMU_DEVICE);
+
+iommu_state = AMD_IOMMU_DEVICE(iommu);
+
+pci_setup_iommu(bus, bridge_host_amd_iommu, iommu_state);
+}
+
 static void mch_realize(PCIDevice *d, Error **errp)
 {
 int i;
@@ -506,8 +520,11 @@ static void mch_realize(PCIDevice *d, Error **errp)
  mch->pci_address_space, &mch->pam_regions[i+1],
  PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE);
 }
-/* Intel IOMMU (VT-d) */
-if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
+
+if (object_property_get_bool(qdev_get_machine(), "iommu", NULL) &&
+MACHINE(qdev_get_machine())->x_iommu_type) {
+mch_init_amdvi(mch);
+} else if (object_property_get_bool(qdev_get_machine(), "iommu", NULL)) {
 mch_init_dmar(mch);
 }
 }
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 7e511e1..539530c 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -24,10 +24,10 @@
 #include "hw/qdev.h"
 #include "sysemu/dma.h"
 
-#define INTEL_IOMMU_STR "intel"
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
+#define INTEL_IOMMU_STR "intel"
 
 /* DMAR Hardware Unit Definition address (IOMMU unit) */
 #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed9ULL
-- 
2.1.4




Re: [Qemu-devel] [V9 0/4] AMD IOMMU

2016-04-24 Thread David Kiarie
Sorry, I keep missing Jan's email...

On Mon, Apr 25, 2016 at 1:12 AM, David Kiarie  wrote:
> Hi all,
>
> The current AMD IOMMU patches that fixes Igor's comments. I got rid of 
> structs and instead
> added individual integer fields into the table data directly, as suggested.
>
> I have also got rid of some un-used macros and fixed a few other 
> miscellaneous things.
>
> David Kiarie (4):
>   hw/i386: Introduce AMD IOMMU
>   hw/i386: ACPI table for AMD IOMMU
>   hw/core: Add AMD IOMMU to machine properties
>   hw/pci-host: Emulate AMD IOMMU
>
>  hw/acpi/aml-build.c   |2 +-
>  hw/acpi/core.c|   13 -
>  hw/core/machine.c |   32 +-
>  hw/i386/Makefile.objs |1 +
>  hw/i386/acpi-build.c  |  101 ++-
>  hw/i386/amd_iommu.c   | 1426 
> +
>  hw/i386/amd_iommu.h   |  398 
>  hw/pci-host/q35.c |   21 +-
>  include/hw/acpi/acpi-defs.h   |   14 +
>  include/hw/acpi/acpi.h|   16 +
>  include/hw/acpi/aml-build.h   |1 +
>  include/hw/boards.h   |1 +
>  include/hw/i386/intel_iommu.h |1 +
>  include/hw/pci/pci.h  |2 +
>  qemu-options.hx   |7 +-
>  util/qemu-config.c|8 +-
>  16 files changed, 2010 insertions(+), 34 deletions(-)
>  create mode 100644 hw/i386/amd_iommu.c
>  create mode 100644 hw/i386/amd_iommu.h
>
> --
> 2.1.4
>



Re: [Qemu-devel] [PATCH v5 15/18] intel_iommu: introduce IEC notifiers

2016-04-28 Thread David Kiarie
On Thu, Apr 28, 2016 at 11:49 AM, Peter Xu  wrote:
> On Thu, Apr 28, 2016 at 10:36:19AM +0200, Jan Kiszka wrote:
>> On 2016-04-28 10:29, Peter Xu wrote:
>> > On Thu, Apr 28, 2016 at 09:26:01AM +0200, Jan Kiszka wrote:
>> >> On 2016-04-28 09:05, Peter Xu wrote:
>> >>> This patch introduces Intel VT-d IEC (Interrupt Entry Cache)
>> >>> invalidation notifier list. When vIOMMU receives IEC invalidate request,
>> >>> all the registered units will be notified with specific invalidation
>> >>> requests.
>> >>
>> >> This should be designed to be IOMMU-agnostic, i.e. become reusable for
>> >> the AMD implementation. I suspect we will have the same need for route
>> >> invalidations there as well...
>> >
>> > Yes possibly...
>> >
>> > I feel like there are lots of things that can be shared between
>> > Intel and AMD IOMMUs. I just do not know what is the most suitable
>> > "extent" that we should abstract these shared functionalities
>> > between the two, and how.
>>
>> A rough indicator: if you add something that has "vtd" in its name to
>> non-vtd code, think twice about some reusable abstraction ;). So,
>> something like "vtd_get_iommu" could already be named and designed to
>> have two provides (e.g. allow an IOMMU to register itself as provider,
>> return that registered instance(s) when requested).
>
> Yes, thanks for the hints. :)
>
> Before that, I was considering that the AMD guy who is going to add
> its support will better consider this and finally make sure the two
> coops well (anyway, I know nothing about AMD IOMMU before reading
> recent patches, and there is still no amd_iommu.c yet for me to read
> at..). But you are right, best to start consider it from the very
> beginning.

I think AMD IOMMU could be a benefit greatly from the Intel IOMMU
cache implementation. There could be a few differences but I think
much of the code could be reused. The thing is, AMD IOMMU spec doesn't
mention anything to do with it's cache design except the available
interface (for system programmers) and I have a bit of a hard time
trying to design a cache from scratch. Trying to do this will however
require me to dig too much into Intel IOMMU and I would prefer to
reserve that for later, probably.

>
>>
>> >
>> > For example, AFAIU, a better solution for current IOMMU
>> > codes (including Intel and AMD) is to provide a common framework
>> > (like...  X86IOMMU?), abstract these shared things out into a
>> > framework, like per device name spaces, iotlb, IEC notifications,
>> > etc... However, that will need a lot of further work. Also, I still
>> > do not know whether this is a good idea even in the future.
>> >
>> > So, will this be a good point that we start to think about common
>> > code blocks for both Intel and AMD IOMMU?
>>
>> The core iommu code can still be refactored later on. I'm now more
>> concerned about the hooks you add to generic code, see above.
>
> Will try to make them look better in v6. Hopefully there will have
> no vtd_*() in common codes. ;)
>
> Thanks!
>
> -- peterx



Re: [Qemu-devel] [V9 2/4] hw/i386: ACPI table for AMD IOMMU

2016-04-29 Thread David Kiarie
On Fri, Apr 29, 2016 at 9:09 AM, Jan Kiszka  wrote:
> On 2016-04-25 00:12, David Kiarie wrote:
>> Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
>> depending on emulated IOMMU
>
> It seems you lack scope descriptions for the PCI devices in the system.
> At least, this is what our jailhouse config generator complains about
> right now (didn't look into details yet). If so, the guest OS will
> likely not configure the IOMMU appropriately as it thinks that the
> devices are passed through anyway.
>
> On Intel, there is an easy way to state "catch them all" in the ACPI
> table. Maybe AMD has this as well so that you don't need to add
> individual devices.

This is what am currently doing. From what I can see, linux correctly
detects the range but I will have a look at it again before sending
the next version.

There was another issue raised by Michael about denying VFIO in case a
user requests for IOMMU support. I did look at this but since VFIO is
started with '-device' I didn't find a way to deny it in case of IOMMU
support except by parsing command line arguments which turned out to
be a bit ugly.

We could exclude VFIO from translation by IOMMU by excluding it from
the scope descriptions but am not quite sure this will remedy all the
problems relating to VFIO and IOMMU. This will also require the device
scope to explicitly list all the devices.

>
> Jan



[Qemu-devel] [V9 0/4] AMD IOMMU

2016-04-29 Thread David Kiarie
These series adds AMD IOMMU support to Qemu. It's currently in the 9th version.

In this series I have (hopefully) addressed all the comments made in the 
previous version.
I have also tested and successfully passed-through PCI device 'ac97' with more 
devices to be tested.


David Kiarie (4):
  hw/i386: Introduce AMD IOMMU
  hw/i386: ACPI table for AMD IOMMU
  hw/core: Add AMD IOMMU to machine properties
  hw/pci-host: Emulate AMD IOMMU

 hw/acpi/aml-build.c   |2 +-
 hw/acpi/core.c|   13 -
 hw/core/machine.c |   33 +-
 hw/i386/Makefile.objs |1 +
 hw/i386/acpi-build.c  |   93 ++-
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 
 hw/pci-host/q35.c |   25 +-
 include/hw/acpi/acpi-defs.h   |   14 +
 include/hw/acpi/acpi.h|   16 +
 include/hw/acpi/aml-build.h   |1 +
 include/hw/boards.h   |7 +
 include/hw/i386/intel_iommu.h |1 +
 include/hw/pci/pci.h  |2 +
 qemu-options.hx   |7 +-
 util/qemu-config.c|8 +-
 16 files changed, 2012 insertions(+), 35 deletions(-)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

-- 
2.1.4




[Qemu-devel] [V9 1/4] hw/i386: Introduce AMD IOMMU

2016-04-29 Thread David Kiarie
Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
The IOMMU does basic translation, error checking and has a
minimal IOTLB implementation

Signed-off-by: David Kiarie 
---
 hw/i386/Makefile.objs |1 +
 hw/i386/amd_iommu.c   | 1426 +
 hw/i386/amd_iommu.h   |  398 ++
 include/hw/pci/pci.h  |2 +
 4 files changed, 1827 insertions(+)
 create mode 100644 hw/i386/amd_iommu.c
 create mode 100644 hw/i386/amd_iommu.h

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index b52d5b8..2f1a265 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -3,6 +3,7 @@ obj-y += multiboot.o
 obj-y += pc.o pc_piix.o pc_q35.o
 obj-y += pc_sysfw.o
 obj-y += intel_iommu.o
+obj-y += amd_iommu.o
 obj-$(CONFIG_XEN) += ../xenpv/ xen/
 
 obj-y += kvmvapic.o
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
new file mode 100644
index 000..eea4fac
--- /dev/null
+++ b/hw/i386/amd_iommu.c
@@ -0,0 +1,1426 @@
+/*
+ * QEMU emulation of AMD IOMMU (AMD-Vi)
+ *
+ * Copyright (C) 2011 Eduard - Gabriel Munteanu
+ * Copyright (C) 2015 David Kiarie, 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Cache implementation inspired by hw/i386/intel_iommu.c
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/amd_iommu.h"
+
+//#define DEBUG_AMD_IOMMU
+#ifdef DEBUG_AMD_IOMMU
+enum {
+DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
+DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU, DEBUG_CUSTOM
+};
+
+#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
+static int iommu_dbgflags = IOMMU_DBGBIT(CUSTOM) | IOMMU_DBGBIT(MMIO);
+
+#define IOMMU_DPRINTF(what, fmt, ...) do { \
+if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
+fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
+## __VA_ARGS__); } \
+} while (0)
+#else
+#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
+#endif
+
+#define ENCODE_EVENT(devid, info, addr, rshift) do { \
+*(uint16_t *)&evt[0] = devid; \
+*(uint8_t *)&evt[3]  = info;  \
+*(uint64_t *)&evt[4] = rshift ? cpu_to_le64(addr) :\
+   cpu_to_le64(addr) >> rshift; \
+} while (0)
+
+typedef struct AMDIOMMUAddressSpace {
+uint8_t bus_num;/* bus number   */
+uint8_t devfn;  /* device function  */
+AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
+MemoryRegion iommu; /* Device's iommu region*/
+AddressSpace as;/* device's corresponding address space */
+} AMDIOMMUAddressSpace;
+
+/* IOMMU cache entry */
+typedef struct IOMMUIOTLBEntry {
+uint64_t gfn;
+uint16_t domid;
+uint64_t devid;
+uint64_t perms;
+uint64_t translated_addr;
+} IOMMUIOTLBEntry;
+
+/* configure MMIO registers at startup/reset */
+static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
+   uint64_t romask, uint64_t w1cmask)
+{
+stq_le_p(&s->mmior[addr], val);
+stq_le_p(&s->romask[addr], romask);
+stq_le_p(&s->w1cmask[addr], w1cmask);
+}
+
+static uint16_t amd_iommu_readw(AMDIOMMUState *s, hwaddr addr)
+{
+return lduw_le_p(&s->mmior[addr]);
+}
+
+static uint32_t amd_iommu_readl(AMDIOMMUState *s, hwaddr addr)
+{
+return ldl_le_p(&s->mmior[addr]);
+}
+
+static uint64_t amd_iommu_readq(AMDIOMMUState *s, hwaddr addr)
+{
+return ldq_le_p(&s->mmior[addr]);
+}
+
+/* internal write */
+static void amd_iommu_writeq_raw(AMDIOMMUState *s, uint64_t val, hwaddr addr)
+{
+stq_le_p(&s->mmior[addr], val);
+}
+
+/* external write */
+static void amd_iommu_writew(AMDIOMMUState *s, hwaddr addr, uint16_t val)
+{
+uint16_t romask = lduw_le_p(&s->romask[addr]);
+uint16_t w1cmask = lduw_le_p(&s->w1cmask[addr]);
+uint16_t oldval = lduw_le_p(&s->mmior[addr]);
+stw_le_p(&s->mmior[addr], (val & ~(val & w1cmask)) | (romask & oldval));
+}
+
+static void amd_iommu_writel(AMDIOMMUState *s, hwaddr addr, uint32_t val)
+{
+uint32_t romask = ldl_le_p(&s->romask[addr]);
+uint32_t w1cmask = ldl_le_p(&s->w1cmask[addr]);
+uint32_t oldval = ldl_le_p(&s->mmior[addr]);
+stl_

[Qemu-devel] [V9 3/4] hw/core: Add AMD IOMMU to machine properties

2016-04-29 Thread David Kiarie
Added an enum, subject to review, to machine properties which
it used to override iommu emulated from Intel to AMD.

Signed-off-by: David Kiarie 
---
 hw/core/machine.c | 33 ++---
 include/hw/boards.h   |  1 +
 include/hw/i386/intel_iommu.h |  1 +
 qemu-options.hx   |  7 +--
 util/qemu-config.c|  8 ++--
 5 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 6dbbc85..ff830f0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -15,6 +15,8 @@
 #include "qapi/error.h"
 #include "qapi-visit.h"
 #include "qapi/visitor.h"
+#include "hw/i386/amd_iommu.h"
+#include "hw/i386/intel_iommu.h"
 #include "hw/sysbus.h"
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
@@ -300,6 +302,27 @@ static void machine_set_iommu(Object *obj, bool value, 
Error **errp)
 ms->iommu = value;
 }
 
+static void machine_set_iommu_override(Object *obj, const char *value,
+   Error **errp)
+{
+MachineState *ms = MACHINE(obj);
+Error *err = NULL;
+
+ms->iommu_type = TYPE_INTEL;
+/* ensure a valid iommu type */
+if (g_strcmp0(value, AMD_IOMMU_STR) == 0) {
+} else if(g_strcmp0(value, INTEL_IOMMU_STR) == 0) {
+} else {
+error_setg(errp, "Invalid IOMMU type %s", value);
+error_propagate(errp, err);
+return;
+}
+
+if ((g_strcmp0(value, AMD_IOMMU_STR) == 0)) {
+ms->iommu_type = TYPE_AMD;
+}
+}
+
 static void machine_set_suppress_vmdesc(Object *obj, bool value, Error **errp)
 {
 MachineState *ms = MACHINE(obj);
@@ -473,10 +496,14 @@ static void machine_initfn(Object *obj)
 "Firmware image",
 NULL);
 object_property_add_bool(obj, "iommu",
- machine_get_iommu,
- machine_set_iommu, NULL);
+ machine_get_iommu, machine_set_iommu, NULL);
 object_property_set_description(obj, "iommu",
-"Set on/off to enable/disable Intel IOMMU 
(VT-d)",
+"Set on to enable IOMMU emulation",
+NULL);
+object_property_add_str(obj, "x-iommu-type",
+NULL, machine_set_iommu_override, NULL);
+object_property_set_description(obj, "x-iommu-type",
+"Set on to override emulated IOMMU to AMD 
IOMMU",
 NULL);
 object_property_add_bool(obj, "suppress-vmdesc",
  machine_get_suppress_vmdesc,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index dbe6745..5b7eeda 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -158,6 +158,7 @@ struct MachineState {
 bool igd_gfx_passthru;
 char *firmware;
 bool iommu;
+IommuType iommu_type;
 bool suppress_vmdesc;
 bool enforce_config_section;
 
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index b024ffa..7e511e1 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -24,6 +24,7 @@
 #include "hw/qdev.h"
 #include "sysemu/dma.h"
 
+#define INTEL_IOMMU_STR "intel"
 #define TYPE_INTEL_IOMMU_DEVICE "intel-iommu"
 #define INTEL_IOMMU_DEVICE(obj) \
  OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
diff --git a/qemu-options.hx b/qemu-options.hx
index 6106520..81217d3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -38,7 +38,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
 "kvm_shadow_mem=size of KVM shadow MMU\n"
 "dump-guest-core=on|off include guest memory in a core 
dump (default=on)\n"
 "mem-merge=on|off controls memory merge support (default: 
on)\n"
-"iommu=on|off controls emulated Intel IOMMU (VT-d) support 
(default=off)\n"
+"iommu=on|off controls emulated IOMMU support(default: 
off)\n"
+"x-iommu-type=amd|intel overrides emulated IOMMU to AMD 
IOMMU (default: intel)\n"
 "igd-passthru=on|off controls IGD GFX passthrough support 
(default=off)\n"
 "aes-key-wrap=on|off controls support for AES key wrapping 
(default=on)\n"
 "dea-key-wrap=on|off controls support for DEA key wrapping 
(default=on)\n"
@@ -74,7 +75,9 @@ Enables or disables memory merge support. This feature, when 
supported by
 the host, de-duplicates identical memory pages among VMs instances
 (enabled b

[Qemu-devel] [V9 2/4] hw/i386: ACPI table for AMD IOMMU

2016-04-29 Thread David Kiarie
Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
depending on emulated IOMMU

Signed-off-by: David Kiarie 
---
 hw/acpi/aml-build.c |  2 +-
 hw/acpi/core.c  | 13 ---
 hw/i386/acpi-build.c| 93 +++--
 include/hw/acpi/acpi-defs.h | 14 +++
 include/hw/acpi/acpi.h  | 16 
 include/hw/acpi/aml-build.h |  1 +
 include/hw/boards.h |  6 +++
 7 files changed, 120 insertions(+), 25 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ab89ca6..da11bf8 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -227,7 +227,7 @@ static void build_extop_package(GArray *package, uint8_t op)
 build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
 }
 
-static void build_append_int_noprefix(GArray *table, uint64_t value, int size)
+void build_append_int_noprefix(GArray *table, uint64_t value, int size)
 {
 int i;
 
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 7925a1a..ee0e687 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -29,19 +29,6 @@
 #include "qapi-visit.h"
 #include "qapi-event.h"
 
-struct acpi_table_header {
-uint16_t _length; /* our length, not actual part of the hdr */
-  /* allows easier parsing for fw_cfg clients */
-char sig[4];  /* ACPI signature (4 ASCII characters) */
-uint32_t length;  /* Length of table, in bytes, including header */
-uint8_t revision; /* ACPI Specification minor version # */
-uint8_t checksum; /* To make sum of entire table == 0 */
-char oem_id[6];   /* OEM identification */
-char oem_table_id[8]; /* OEM table identification */
-uint32_t oem_revision;/* OEM revision number */
-char asl_compiler_id[4];  /* ASL compiler vendor ID */
-uint32_t asl_compiler_revision; /* ASL compiler revision number */
-} QEMU_PACKED;
 
 #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
 #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6477003..74ae994 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"
@@ -59,6 +60,8 @@
 #include "qapi/qmp/qint.h"
 #include "qom/qom-qobject.h"
 
+#include "hw/boards.h"
+
 /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
  * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
  * a little bit, there should be plenty of free space since the DSDT
@@ -2598,6 +2601,77 @@ 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;
+
+/* IVRS definition  - table header has an extra 2-byte field */
+acpi_data_push(table_data, (sizeof(acpi_table_header) - 2));
+/* common virtualization information */
+build_append_int_noprefix(table_data, AMD_IOMMU_HOST_ADDRESS_WIDTH << 8, 
4);
+/* reserved */
+build_append_int_noprefix(table_data, 0, 8);
+
+AMDIOMMUState *s = (AMDIOMMUState *)object_resolve_path_type("",
+TYPE_AMD_IOMMU_DEVICE, &iommu_ambig);
+
+/* IVDB definition - type 10h */
+if (!iommu_ambig) {
+/* IVHD definition - type 10h */
+build_append_int_noprefix(table_data, 0x10, 1);
+/* virtualization flags */
+build_append_int_noprefix(table_data, (IVHD_HT_TUNEN |
+ IVHD_PPRSUP | IVHD_IOTLBSUP | IVHD_PREFSUP), 1);
+/* ivhd length */
+build_append_int_noprefix(table_data, 0x20, 2);
+/* iommu device id */
+build_append_int_noprefix(table_data, PCI_DEVICE_ID_RD890_IOMMU, 2);
+/* offset of capability registers */
+build_append_int_noprefix(table_data, s->capab_offset, 2);
+/* mmio base register */
+build_append_int_noprefix(table_data, s->mmio.addr, 8);
+/* pci segment */
+build_append_int_noprefix(table_data, 0, 2);
+/* interrupt numbers */
+build_append_int_noprefix(table_data, 0, 2);
+/* feature reporting */
+build_append_int_noprefix(table_data, (IVHD_EFR_GTSUP |
+IVHD_EFR_HATS | IVHD_EFR_GATS), 4);
+/* 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
+

Re: [Qemu-devel] [V9 2/4] hw/i386: ACPI table for AMD IOMMU

2016-05-02 Thread David Kiarie
On Sun, May 1, 2016 at 4:45 PM, Michael S. Tsirkin  wrote:
> On Sat, Apr 30, 2016 at 01:42:41AM +0300, David Kiarie wrote:
>> Add IVRS table for AMD IOMMU. Generate IVRS or DMAR
>> depending on emulated IOMMU
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/acpi/aml-build.c |  2 +-
>>  hw/acpi/core.c  | 13 ---
>>  hw/i386/acpi-build.c| 93 
>> +++--
>>  include/hw/acpi/acpi-defs.h | 14 +++
>>  include/hw/acpi/acpi.h  | 16 
>>  include/hw/acpi/aml-build.h |  1 +
>>  include/hw/boards.h |  6 +++
>>  7 files changed, 120 insertions(+), 25 deletions(-)
>>
>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>> index ab89ca6..da11bf8 100644
>> --- a/hw/acpi/aml-build.c
>> +++ b/hw/acpi/aml-build.c
>> @@ -227,7 +227,7 @@ static void build_extop_package(GArray *package, uint8_t 
>> op)
>>  build_prepend_byte(package, 0x5B); /* ExtOpPrefix */
>>  }
>>
>> -static void build_append_int_noprefix(GArray *table, uint64_t value, int 
>> size)
>> +void build_append_int_noprefix(GArray *table, uint64_t value, int size)
>>  {
>>  int i;
>>
>> diff --git a/hw/acpi/core.c b/hw/acpi/core.c
>> index 7925a1a..ee0e687 100644
>> --- a/hw/acpi/core.c
>> +++ b/hw/acpi/core.c
>> @@ -29,19 +29,6 @@
>>  #include "qapi-visit.h"
>>  #include "qapi-event.h"
>>
>> -struct acpi_table_header {
>> -uint16_t _length; /* our length, not actual part of the hdr */
>> -  /* allows easier parsing for fw_cfg clients */
>> -char sig[4];  /* ACPI signature (4 ASCII characters) */
>> -uint32_t length;  /* Length of table, in bytes, including 
>> header */
>> -uint8_t revision; /* ACPI Specification minor version # */
>> -uint8_t checksum; /* To make sum of entire table == 0 */
>> -char oem_id[6];   /* OEM identification */
>> -char oem_table_id[8]; /* OEM table identification */
>> -uint32_t oem_revision;/* OEM revision number */
>> -char asl_compiler_id[4];  /* ASL compiler vendor ID */
>> -uint32_t asl_compiler_revision; /* ASL compiler revision number */
>> -} QEMU_PACKED;
>>
>>  #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header)
>>  #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t)  /* size of the extra prefix */
>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> index 6477003..74ae994 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"
>> @@ -59,6 +60,8 @@
>>  #include "qapi/qmp/qint.h"
>>  #include "qom/qom-qobject.h"
>>
>> +#include "hw/boards.h"
>> +
>>  /* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
>>   * -M pc-i440fx-2.0.  Even if the actual amount of AML generated grows
>>   * a little bit, there should be plenty of free space since the DSDT
>> @@ -2598,6 +2601,77 @@ 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;
>> +
>> +/* IVRS definition  - table header has an extra 2-byte field */
>> +acpi_data_push(table_data, (sizeof(acpi_table_header) - 2));
>
> why won't build_header overwrite the extra fields?
> Even if not, that's too hacky. Pls find another way to do this.

I was advised to do this by Igor, to get rid of structs defining IVRS
table. He actually said it should be done
acpi_data_push(table_data, (sizeof(acpi_table_header) - 2));
but looking at acpi_table_header, I noted there's an extra 2-byte
field for internal use which corrupts IVRS.

The other way I could do this, since I know the size of IVRS table, is
to use a constant
acpi_data_push(table_data, 0x30));
am not sure whether this isn't even more hacky otherwise I'd have to
go back to using the original structs.

>
>> +/* common virtualization information */
>> +build_append_int_noprefix(table_data, AMD

Re: [Qemu-devel] [V9 0/4] AMD IOMMU

2016-05-02 Thread David Kiarie
On Sun, May 1, 2016 at 5:00 PM, Michael S. Tsirkin  wrote:
> On Sun, May 01, 2016 at 04:47:44PM +0300, Michael S. Tsirkin wrote:
>> On Sat, Apr 30, 2016 at 01:42:39AM +0300, David Kiarie wrote:
>> > These series adds AMD IOMMU support to Qemu. It's currently in the 9th 
>> > version.
>> >
>> > In this series I have (hopefully) addressed all the comments made in the 
>> > previous version.
>>
>> changelog?
>>
>> > I have also tested and successfully passed-through PCI device 'ac97' with 
>> > more devices to be tested.
>>
>>
>> A fundamental problem with AMD IOMMUs is that the VMM must write-protect
>> guest I/O page tables from the guest in order to intercept all guest
>> updates and propagate the updates to the shadow I/O page tables.
>>
>> AMD manual says as much.
>
> Actually while it says so, it's wrong.
> There's an NPcache flag which makes guest to invalidations
> for invalid to valid transitions.
>
>> Until this is implemented, I think device assignment must be disabled
>> when AMD IOMMU is in use.
>
> So I take this back. I would, however, like to see how this
> interacts with Aviv's patches enabling VFIO support for IOMMU.
>
The initial consensus was to deny VFIO when user requests for IOMMU
and I did actually look at that but I can't get an obvious way to
disable, or even tell that a user requested for a device when they do
so via '-device'. The only way to disable VFIO was parsing the command
line argument which seemed very ugly.

Other than that, I would prefer not to add more features to this
patchset but I will still be working on IOMMU for the next few months
so I'll probably look at that.

>>
>> >
>> > David Kiarie (4):
>> >   hw/i386: Introduce AMD IOMMU
>> >   hw/i386: ACPI table for AMD IOMMU
>> >   hw/core: Add AMD IOMMU to machine properties
>> >   hw/pci-host: Emulate AMD IOMMU
>> >
>> >  hw/acpi/aml-build.c   |2 +-
>> >  hw/acpi/core.c|   13 -
>> >  hw/core/machine.c |   33 +-
>> >  hw/i386/Makefile.objs |1 +
>> >  hw/i386/acpi-build.c  |   93 ++-
>> >  hw/i386/amd_iommu.c   | 1426 
>> > +
>> >  hw/i386/amd_iommu.h   |  398 
>> >  hw/pci-host/q35.c |   25 +-
>> >  include/hw/acpi/acpi-defs.h   |   14 +
>> >  include/hw/acpi/acpi.h|   16 +
>> >  include/hw/acpi/aml-build.h   |1 +
>> >  include/hw/boards.h   |7 +
>> >  include/hw/i386/intel_iommu.h |1 +
>> >  include/hw/pci/pci.h  |2 +
>> >  qemu-options.hx   |7 +-
>> >  util/qemu-config.c|8 +-
>> >  16 files changed, 2012 insertions(+), 35 deletions(-)
>> >  create mode 100644 hw/i386/amd_iommu.c
>> >  create mode 100644 hw/i386/amd_iommu.h
>> >
>> > --
>> > 2.1.4



Re: [Qemu-devel] [V9 1/4] hw/i386: Introduce AMD IOMMU

2016-05-03 Thread David Kiarie
On Sun, May 1, 2016 at 5:14 PM, Michael S. Tsirkin  wrote:
> On Sat, Apr 30, 2016 at 01:42:40AM +0300, David Kiarie wrote:
>> Add AMD IOMMU emulaton to Qemu in addition to Intel IOMMU
>> The IOMMU does basic translation, error checking and has a
>> minimal IOTLB implementation
>>
>> Signed-off-by: David Kiarie 
>> ---
>>  hw/i386/Makefile.objs |1 +
>>  hw/i386/amd_iommu.c   | 1426 
>> +
>>  hw/i386/amd_iommu.h   |  398 ++
>>  include/hw/pci/pci.h  |2 +
>>  4 files changed, 1827 insertions(+)
>>  create mode 100644 hw/i386/amd_iommu.c
>>  create mode 100644 hw/i386/amd_iommu.h
>>
>> diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
>> index b52d5b8..2f1a265 100644
>> --- a/hw/i386/Makefile.objs
>> +++ b/hw/i386/Makefile.objs
>> @@ -3,6 +3,7 @@ obj-y += multiboot.o
>>  obj-y += pc.o pc_piix.o pc_q35.o
>>  obj-y += pc_sysfw.o
>>  obj-y += intel_iommu.o
>> +obj-y += amd_iommu.o
>>  obj-$(CONFIG_XEN) += ../xenpv/ xen/
>>
>>  obj-y += kvmvapic.o
>> diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
>> new file mode 100644
>> index 000..eea4fac
>> --- /dev/null
>> +++ b/hw/i386/amd_iommu.c
>> @@ -0,0 +1,1426 @@
>> +/*
>> + * QEMU emulation of AMD IOMMU (AMD-Vi)
>> + *
>> + * Copyright (C) 2011 Eduard - Gabriel Munteanu
>> + * Copyright (C) 2015 David Kiarie, 
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or
>> + * (at your option) any later version.
>> +
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> +
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, see <http://www.gnu.org/licenses/>.
>> + *
>> + * Cache implementation inspired by hw/i386/intel_iommu.c
>> + *
>> + */
>> +#include "qemu/osdep.h"
>> +#include "hw/i386/amd_iommu.h"
>> +
>> +//#define DEBUG_AMD_IOMMU
>> +#ifdef DEBUG_AMD_IOMMU
>> +enum {
>> +DEBUG_GENERAL, DEBUG_CAPAB, DEBUG_MMIO, DEBUG_ELOG,
>> +DEBUG_CACHE, DEBUG_COMMAND, DEBUG_MMU, DEBUG_CUSTOM
>> +};
>> +
>> +#define IOMMU_DBGBIT(x)   (1 << DEBUG_##x)
>> +static int iommu_dbgflags = IOMMU_DBGBIT(CUSTOM) | IOMMU_DBGBIT(MMIO);
>> +
>> +#define IOMMU_DPRINTF(what, fmt, ...) do { \
>> +if (iommu_dbgflags & IOMMU_DBGBIT(what)) { \
>> +fprintf(stderr, "(amd-iommu)%s: " fmt "\n", __func__, \
>> +## __VA_ARGS__); } \
>> +} while (0)
>> +#else
>> +#define IOMMU_DPRINTF(what, fmt, ...) do {} while (0)
>> +#endif
>> +
>> +#define ENCODE_EVENT(devid, info, addr, rshift) do { \
>> +*(uint16_t *)&evt[0] = devid; \
>> +*(uint8_t *)&evt[3]  = info;  \
>> +*(uint64_t *)&evt[4] = rshift ? cpu_to_le64(addr) :\
>> +   cpu_to_le64(addr) >> rshift; \
>> +} while (0)
>> +
>> +typedef struct AMDIOMMUAddressSpace {
>> +uint8_t bus_num;/* bus number   */
>> +uint8_t devfn;  /* device function  */
>> +AMDIOMMUState *iommu_state; /* IOMMU - one per machine  */
>> +MemoryRegion iommu; /* Device's iommu region*/
>> +AddressSpace as;/* device's corresponding address space */
>> +} AMDIOMMUAddressSpace;
>> +
>> +/* IOMMU cache entry */
>> +typedef struct IOMMUIOTLBEntry {
>> +uint64_t gfn;
>> +uint16_t domid;
>> +uint64_t devid;
>> +uint64_t perms;
>> +uint64_t translated_addr;
>> +} IOMMUIOTLBEntry;
>> +
>> +/* configure MMIO registers at startup/reset */
>> +static void amd_iommu_set_quad(AMDIOMMUState *s, hwaddr addr, uint64_t val,
>> +   uint64_t romask, uint64_t w1cmask)
>> +{
>> +stq_le_p(&s->mmior[addr], val);
>> +stq_le_p(&s->romask[addr], romask);
>> +stq_le_p(&s->w1cmask[addr], w1cmask);
>> +}
>> +
>> +static uint16_t amd_iommu_re

Re: [Qemu-devel] [V9 0/4] AMD IOMMU

2016-05-04 Thread David Kiarie
On Wed, May 4, 2016 at 9:12 AM, Jan Kiszka  wrote:
> On 2016-04-30 00:42, David Kiarie wrote:
>> These series adds AMD IOMMU support to Qemu. It's currently in the 9th 
>> version.
>>
>> In this series I have (hopefully) addressed all the comments made in the 
>> previous version.
>> I have also tested and successfully passed-through PCI device 'ac97' with 
>> more devices to be tested.
>>
>
> I've done some basic testing with a Jailhouse setup and found it
> working. The ACPI table is now properly parsed and the DMA remapping was
> not disturbing the system after Jailhouse was activated.
>
> However, it was also still not intervening after I started to corrupt
> the configuration, removed DMA target properties from most of the RAM or
> dropped PCI devices.

This means you're invalidating DTEs ?

>
> You are not dropping invalid remapping requests, are you? According to
> the logs, you are detecting them at least:
>
> (amd-iommu)amd_iommu_get_dte: Device Table at 0x3b0d4000
> (amd-iommu)amd_iommu_get_dte: Pte entry at 0x0 is invalid
> (amd-iommu)amd_iommu_translate: devid: 00:02.0 gpa 0x32f39480 hpa 0x32f39000
>
> It's a bit hard to test right now if remapping is actually properly
> working in all important cases if you do not reject invalid ones.
>
> Jan
>



  1   2   3   4   >