From: Wei Wang <wei.wang2@amd.com>
To: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: "xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>
Subject: [Qemu-devel] [PATCH] Add amd iommu emulation for Xen.
Date: Wed, 26 Sep 2012 16:45:55 +0200 [thread overview]
Message-ID: <50631523.3060602@amd.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 88 bytes --]
HI,
Attached patch adds amd iommu emulation for Xen. Please review it.
Thanks,
Wei
[-- Attachment #2: 0001-Add-amd-iommu-emulation-for-Xen.patch --]
[-- Type: text/plain, Size: 8114 bytes --]
From 122517435641384e4f5e36eaad8302ff273648e8 Mon Sep 17 00:00:00 2001
From: Wei Wang <wei.wang2@amd.com>
Date: Wed, 26 Sep 2012 16:43:40 +0200
Subject: [PATCH] Add amd iommu emulation for Xen.
To passthrough amd southern islands series gpu to guest, a virtual iommu device must
be registered on qemu pci bus. It uses a new hypercall xc_domain_update_iommu_msi
to notify xen the msi vector of iommu.
Signed-off-by: Wei Wang <wei.wang2@amd.com>
---
hw/i386/Makefile.objs | 2 +-
hw/pc_piix.c | 6 ++
hw/xen_iommu.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/xen_pt.h | 1 +
4 files changed, 199 insertions(+), 1 deletions(-)
create mode 100644 hw/xen_iommu.c
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 8c764bb..8b231ab 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -8,7 +8,7 @@ obj-y += pc_piix.o
obj-y += pc_sysfw.o
obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
-obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
+obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_iommu.o
obj-y += kvm/
obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index fd5898f..0b5d034 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -46,6 +46,9 @@
#ifdef CONFIG_XEN
# include <xen/hvm/hvm_info_table.h>
#endif
+#ifdef CONFIG_XEN_PCI_PASSTHROUGH
+# include "xen_pt.h"
+#endif
#define MAX_IDE_BUS 2
@@ -228,6 +231,9 @@ static void pc_init1(MemoryRegion *system_memory,
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
if (xen_enabled()) {
pci_create_simple(pci_bus, -1, "xen-platform");
+#ifdef CONFIG_XEN_PCI_PASSTHROUGH
+ xen_pt_iommu_create(pci_bus);
+#endif
}
/* init basic PC hardware */
diff --git a/hw/xen_iommu.c b/hw/xen_iommu.c
new file mode 100644
index 0000000..9a9ede4
--- /dev/null
+++ b/hw/xen_iommu.c
@@ -0,0 +1,191 @@
+/*
+ * amd iommu support
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * Author: Wei Wang <wei.wang2@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "xen_pt.h"
+#include "xen_backend.h"
+
+#pragma pack(1)
+
+typedef struct iommu_capability_block {
+ uint8_t id;
+ uint8_t next_ptr;
+ uint8_t cap_info;
+ uint8_t flags;
+ uint32_t base_low;
+ uint32_t base_high;
+ uint32_t range;
+ uint32_t misc;
+} iommu_capability_t;
+
+typedef struct msi_capability_block {
+ uint8_t id;
+ uint8_t next_ptr;
+ uint16_t msg_ctrl;
+ uint32_t addr_low;
+ uint32_t addr_high;
+ uint32_t msi_data;
+} msi_capability_t;
+
+struct amd_iommu_config {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t command;
+ uint16_t status;
+ uint8_t revision;
+ uint8_t api;
+ uint8_t subclass;
+ uint8_t class;
+ uint8_t cache_line_size;
+ uint8_t latency_timer;
+ uint8_t header_type;
+ uint8_t bist;
+ uint32_t base_address_regs[6];
+ uint32_t reserved1;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_id;
+ uint32_t rom_addr;
+ uint8_t cap_ptr;
+ uint8_t reserved3[3];
+ uint32_t reserved4;
+ uint8_t interrupt_line;
+ uint8_t interrupt_pin;
+ uint8_t min_gnt;
+ uint8_t max_lat;
+ iommu_capability_t cap;
+ msi_capability_t msi;
+};
+#pragma pack()
+
+#ifndef PCI_CAP_ID_SEC
+#define PCI_CAP_ID_SEC 0x0F
+#endif
+#define PCI_CLASS_SYSTEM_AMD_IOMMU 0x0806
+#define PCI_DEVICE_AMD_IOMMU_V2 0xFFFF
+#define IOMMU_CAP_FLAGS_IOTLB 0
+#define IOMMU_CAP_FLAGS_EFRSUP 3
+#define IOMMU_CAP_TYPE 0x3
+#define IOMMU_CAP_REV 0x1
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_TARGET_CPU_SHIFT 12
+#define PCI_STATUS_CAPABILITIES 0x010
+
+static void amd_iommu_pci_write_config(PCIDevice *d, uint32_t address,
+ uint32_t val, int len)
+{
+ struct amd_iommu_config *iommu_config;
+ uint64_t msi_addr;
+ uint32_t msi_data;
+ uint8_t offset_msi_data, vector, en;
+ uint8_t dest_mode, dest, delivery_mode, trig_mode;
+
+ pci_default_write_config(d, address, val, len);
+
+ iommu_config = (struct amd_iommu_config *)d->config;
+
+ offset_msi_data = iommu_config->cap.next_ptr + sizeof(uint32_t) +
+ sizeof(uint64_t);
+
+ if ( address == offset_msi_data )
+ {
+ msi_addr = (uint64_t)iommu_config->msi.addr_high << 32 |
+ iommu_config->msi.addr_low;
+ msi_data = val;
+ vector = msi_data & 0xFF;
+ en = iommu_config->msi.msg_ctrl & 0x1;
+
+ if ( !en )
+ return;
+
+ dest_mode = (msi_addr >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;
+ dest = (msi_addr >> MSI_TARGET_CPU_SHIFT) & 0xff;
+ delivery_mode = (msi_data >> MSI_DATA_DELIVERY_SHIFT) & 0x7;
+ trig_mode = (msi_data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
+
+ xc_domain_update_iommu_msi(xen_xc, xen_domid, vector, dest,
+ dest_mode, delivery_mode, trig_mode);
+ }
+}
+
+static int amd_iommu_initfn(PCIDevice *d)
+{
+ struct amd_iommu_config *cfg;
+
+ cfg = (struct amd_iommu_config *)d->config;
+
+ cfg->status = PCI_STATUS_CAPABILITIES;
+ cfg->cap_ptr = sizeof(struct amd_iommu_config) -
+ sizeof(iommu_capability_t)- sizeof(msi_capability_t);
+
+ cfg->cap.id = PCI_CAP_ID_SEC;
+ cfg->cap.cap_info = IOMMU_CAP_REV << 3 | IOMMU_CAP_TYPE;
+
+ cfg->cap.flags |= 1 << IOMMU_CAP_FLAGS_IOTLB;
+ cfg->cap.flags |= 1 << IOMMU_CAP_FLAGS_EFRSUP;
+
+ cfg->cap.next_ptr = cfg->cap_ptr + sizeof(iommu_capability_t);
+ cfg->msi.id = PCI_CAP_ID_MSI;
+ cfg->msi.msg_ctrl = PCI_MSI_FLAGS_64BIT;
+
+ return 0;
+}
+
+static void xen_iommu_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = amd_iommu_initfn;
+ k->vendor_id = PCI_VENDOR_ID_AMD;
+ k->device_id = PCI_DEVICE_AMD_IOMMU_V2;
+ k->class_id = PCI_CLASS_SYSTEM_AMD_IOMMU;
+ k->subsystem_vendor_id = PCI_VENDOR_ID_AMD;
+ k->subsystem_id = PCI_DEVICE_AMD_IOMMU_V2;
+ k->config_write = amd_iommu_pci_write_config;
+};
+
+typedef struct XenIommuState {
+ PCIDevice dev;
+} XenIommuState;
+
+static TypeInfo xen_iommu_info = {
+ .name = "xen-iommu",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XenIommuState),
+ .class_init = xen_iommu_class_init,
+};
+
+static void xen_iommu_register_types(void)
+{
+ type_register_static(&xen_iommu_info);
+}
+
+type_init(xen_iommu_register_types)
+
+void xen_pt_iommu_create(PCIBus *pci_bus)
+{
+ char *path;
+ char *iommu;
+ struct xs_handle *xs = xs_open(0);
+
+ path = xs_get_domain_path(xs, xen_domid);
+ iommu = xenstore_read_str(path, "guest_iommu");
+
+ if ( !strcmp(iommu, "1") )
+ pci_create_simple(pci_bus, -1, "xen-iommu");
+
+ free(path);
+ xs_close(xs);
+}
diff --git a/hw/xen_pt.h b/hw/xen_pt.h
index 112477a..b54a0fb 100644
--- a/hw/xen_pt.h
+++ b/hw/xen_pt.h
@@ -291,6 +291,7 @@ void xen_pt_msix_delete(XenPCIPassthroughState *s);
int xen_pt_msix_update(XenPCIPassthroughState *s);
int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
void xen_pt_msix_disable(XenPCIPassthroughState *s);
+void xen_pt_iommu_create(PCIBus *pci_bus);
static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
{
--
1.7.4
WARNING: multiple messages have this Message-ID (diff)
From: Wei Wang <wei.wang2@amd.com>
To: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: "xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>
Subject: [PATCH] Add amd iommu emulation for Xen.
Date: Wed, 26 Sep 2012 16:45:55 +0200 [thread overview]
Message-ID: <50631523.3060602@amd.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 88 bytes --]
HI,
Attached patch adds amd iommu emulation for Xen. Please review it.
Thanks,
Wei
[-- Attachment #2: 0001-Add-amd-iommu-emulation-for-Xen.patch --]
[-- Type: text/plain, Size: 8114 bytes --]
From 122517435641384e4f5e36eaad8302ff273648e8 Mon Sep 17 00:00:00 2001
From: Wei Wang <wei.wang2@amd.com>
Date: Wed, 26 Sep 2012 16:43:40 +0200
Subject: [PATCH] Add amd iommu emulation for Xen.
To passthrough amd southern islands series gpu to guest, a virtual iommu device must
be registered on qemu pci bus. It uses a new hypercall xc_domain_update_iommu_msi
to notify xen the msi vector of iommu.
Signed-off-by: Wei Wang <wei.wang2@amd.com>
---
hw/i386/Makefile.objs | 2 +-
hw/pc_piix.c | 6 ++
hw/xen_iommu.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/xen_pt.h | 1 +
4 files changed, 199 insertions(+), 1 deletions(-)
create mode 100644 hw/xen_iommu.c
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 8c764bb..8b231ab 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -8,7 +8,7 @@ obj-y += pc_piix.o
obj-y += pc_sysfw.o
obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen-host-pci-device.o
-obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o
+obj-$(CONFIG_XEN_PCI_PASSTHROUGH) += xen_pt.o xen_pt_config_init.o xen_pt_msi.o xen_iommu.o
obj-y += kvm/
obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index fd5898f..0b5d034 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -46,6 +46,9 @@
#ifdef CONFIG_XEN
# include <xen/hvm/hvm_info_table.h>
#endif
+#ifdef CONFIG_XEN_PCI_PASSTHROUGH
+# include "xen_pt.h"
+#endif
#define MAX_IDE_BUS 2
@@ -228,6 +231,9 @@ static void pc_init1(MemoryRegion *system_memory,
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
if (xen_enabled()) {
pci_create_simple(pci_bus, -1, "xen-platform");
+#ifdef CONFIG_XEN_PCI_PASSTHROUGH
+ xen_pt_iommu_create(pci_bus);
+#endif
}
/* init basic PC hardware */
diff --git a/hw/xen_iommu.c b/hw/xen_iommu.c
new file mode 100644
index 0000000..9a9ede4
--- /dev/null
+++ b/hw/xen_iommu.c
@@ -0,0 +1,191 @@
+/*
+ * amd iommu support
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ * Author: Wei Wang <wei.wang2@amd.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include "xen_pt.h"
+#include "xen_backend.h"
+
+#pragma pack(1)
+
+typedef struct iommu_capability_block {
+ uint8_t id;
+ uint8_t next_ptr;
+ uint8_t cap_info;
+ uint8_t flags;
+ uint32_t base_low;
+ uint32_t base_high;
+ uint32_t range;
+ uint32_t misc;
+} iommu_capability_t;
+
+typedef struct msi_capability_block {
+ uint8_t id;
+ uint8_t next_ptr;
+ uint16_t msg_ctrl;
+ uint32_t addr_low;
+ uint32_t addr_high;
+ uint32_t msi_data;
+} msi_capability_t;
+
+struct amd_iommu_config {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t command;
+ uint16_t status;
+ uint8_t revision;
+ uint8_t api;
+ uint8_t subclass;
+ uint8_t class;
+ uint8_t cache_line_size;
+ uint8_t latency_timer;
+ uint8_t header_type;
+ uint8_t bist;
+ uint32_t base_address_regs[6];
+ uint32_t reserved1;
+ uint16_t subsystem_vendor_id;
+ uint16_t subsystem_id;
+ uint32_t rom_addr;
+ uint8_t cap_ptr;
+ uint8_t reserved3[3];
+ uint32_t reserved4;
+ uint8_t interrupt_line;
+ uint8_t interrupt_pin;
+ uint8_t min_gnt;
+ uint8_t max_lat;
+ iommu_capability_t cap;
+ msi_capability_t msi;
+};
+#pragma pack()
+
+#ifndef PCI_CAP_ID_SEC
+#define PCI_CAP_ID_SEC 0x0F
+#endif
+#define PCI_CLASS_SYSTEM_AMD_IOMMU 0x0806
+#define PCI_DEVICE_AMD_IOMMU_V2 0xFFFF
+#define IOMMU_CAP_FLAGS_IOTLB 0
+#define IOMMU_CAP_FLAGS_EFRSUP 3
+#define IOMMU_CAP_TYPE 0x3
+#define IOMMU_CAP_REV 0x1
+
+#define MSI_DATA_VECTOR_SHIFT 0
+#define MSI_DATA_DELIVERY_SHIFT 8
+#define MSI_DATA_LEVEL_SHIFT 14
+#define MSI_DATA_TRIGGER_SHIFT 15
+#define MSI_ADDR_DESTID_MASK 0xfff0000f
+#define MSI_ADDR_DESTMODE_SHIFT 2
+#define MSI_ADDR_REDIRECTION_SHIFT 3
+#define MSI_TARGET_CPU_SHIFT 12
+#define PCI_STATUS_CAPABILITIES 0x010
+
+static void amd_iommu_pci_write_config(PCIDevice *d, uint32_t address,
+ uint32_t val, int len)
+{
+ struct amd_iommu_config *iommu_config;
+ uint64_t msi_addr;
+ uint32_t msi_data;
+ uint8_t offset_msi_data, vector, en;
+ uint8_t dest_mode, dest, delivery_mode, trig_mode;
+
+ pci_default_write_config(d, address, val, len);
+
+ iommu_config = (struct amd_iommu_config *)d->config;
+
+ offset_msi_data = iommu_config->cap.next_ptr + sizeof(uint32_t) +
+ sizeof(uint64_t);
+
+ if ( address == offset_msi_data )
+ {
+ msi_addr = (uint64_t)iommu_config->msi.addr_high << 32 |
+ iommu_config->msi.addr_low;
+ msi_data = val;
+ vector = msi_data & 0xFF;
+ en = iommu_config->msi.msg_ctrl & 0x1;
+
+ if ( !en )
+ return;
+
+ dest_mode = (msi_addr >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;
+ dest = (msi_addr >> MSI_TARGET_CPU_SHIFT) & 0xff;
+ delivery_mode = (msi_data >> MSI_DATA_DELIVERY_SHIFT) & 0x7;
+ trig_mode = (msi_data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;
+
+ xc_domain_update_iommu_msi(xen_xc, xen_domid, vector, dest,
+ dest_mode, delivery_mode, trig_mode);
+ }
+}
+
+static int amd_iommu_initfn(PCIDevice *d)
+{
+ struct amd_iommu_config *cfg;
+
+ cfg = (struct amd_iommu_config *)d->config;
+
+ cfg->status = PCI_STATUS_CAPABILITIES;
+ cfg->cap_ptr = sizeof(struct amd_iommu_config) -
+ sizeof(iommu_capability_t)- sizeof(msi_capability_t);
+
+ cfg->cap.id = PCI_CAP_ID_SEC;
+ cfg->cap.cap_info = IOMMU_CAP_REV << 3 | IOMMU_CAP_TYPE;
+
+ cfg->cap.flags |= 1 << IOMMU_CAP_FLAGS_IOTLB;
+ cfg->cap.flags |= 1 << IOMMU_CAP_FLAGS_EFRSUP;
+
+ cfg->cap.next_ptr = cfg->cap_ptr + sizeof(iommu_capability_t);
+ cfg->msi.id = PCI_CAP_ID_MSI;
+ cfg->msi.msg_ctrl = PCI_MSI_FLAGS_64BIT;
+
+ return 0;
+}
+
+static void xen_iommu_class_init(ObjectClass *klass, void *data)
+{
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = amd_iommu_initfn;
+ k->vendor_id = PCI_VENDOR_ID_AMD;
+ k->device_id = PCI_DEVICE_AMD_IOMMU_V2;
+ k->class_id = PCI_CLASS_SYSTEM_AMD_IOMMU;
+ k->subsystem_vendor_id = PCI_VENDOR_ID_AMD;
+ k->subsystem_id = PCI_DEVICE_AMD_IOMMU_V2;
+ k->config_write = amd_iommu_pci_write_config;
+};
+
+typedef struct XenIommuState {
+ PCIDevice dev;
+} XenIommuState;
+
+static TypeInfo xen_iommu_info = {
+ .name = "xen-iommu",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(XenIommuState),
+ .class_init = xen_iommu_class_init,
+};
+
+static void xen_iommu_register_types(void)
+{
+ type_register_static(&xen_iommu_info);
+}
+
+type_init(xen_iommu_register_types)
+
+void xen_pt_iommu_create(PCIBus *pci_bus)
+{
+ char *path;
+ char *iommu;
+ struct xs_handle *xs = xs_open(0);
+
+ path = xs_get_domain_path(xs, xen_domid);
+ iommu = xenstore_read_str(path, "guest_iommu");
+
+ if ( !strcmp(iommu, "1") )
+ pci_create_simple(pci_bus, -1, "xen-iommu");
+
+ free(path);
+ xs_close(xs);
+}
diff --git a/hw/xen_pt.h b/hw/xen_pt.h
index 112477a..b54a0fb 100644
--- a/hw/xen_pt.h
+++ b/hw/xen_pt.h
@@ -291,6 +291,7 @@ void xen_pt_msix_delete(XenPCIPassthroughState *s);
int xen_pt_msix_update(XenPCIPassthroughState *s);
int xen_pt_msix_update_remap(XenPCIPassthroughState *s, int bar_index);
void xen_pt_msix_disable(XenPCIPassthroughState *s);
+void xen_pt_iommu_create(PCIBus *pci_bus);
static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
{
--
1.7.4
next reply other threads:[~2012-09-26 14:44 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-09-26 14:45 Wei Wang [this message]
2012-09-26 14:45 ` [PATCH] Add amd iommu emulation for Xen Wei Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50631523.3060602@amd.com \
--to=wei.wang2@amd.com \
--cc=qemu-devel@nongnu.org \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.