All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wei Wang2 <wei.wang2@amd.com>
To: xen-devel@lists.xensource.com
Cc: Keir Fraser <keir@xen.org>, Jan Beulich <JBeulich@suse.com>
Subject: [PATCH] xen-qemu: register virtual iommu device on qemu pci bus
Date: Wed, 14 Dec 2011 16:38:04 +0100	[thread overview]
Message-ID: <201112141638.05345.wei.wang2@amd.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 193 bytes --]

Attached patch is for qemu to register iommu device on pci bus. Guest OS 
requires this to access iommu pci config space in some cases.
Thanks,
Wei

Signed-off-by: Wei Wang <wei.wang2@amd.com>

[-- Attachment #2: qemu-iommuv2.diff --]
[-- Type: text/x-diff, Size: 6577 bytes --]

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 919937f..d6f35d8 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -4402,5 +4414,94 @@ int pt_init(PCIBus *e_bus)
     memset(&dpci_infos, 0, sizeof(struct dpci_infos));
     dpci_infos.e_bus      = e_bus;
 
+    amd_iommu_init(e_bus);
     return 0;
 }
+
+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 ( !vector || !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(xc_handle, domid, vector, dest, 
+                                   dest_mode, delivery_mode, trig_mode);
+    }
+}
+
+#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
+
+extern int guest_iommu;
+void amd_iommu_init(PCIBus *bus)
+{
+    PCIDevice *amd_iommu;
+    struct amd_iommu_config *cfg;
+    struct pt_dev *assigned_device = NULL;
+
+    if ( !guest_iommu )
+        return;
+
+    amd_iommu = pci_register_device(bus, "AMD IOMMU v2", 
+                                    sizeof(struct PCIDevice), -1,
+                                    NULL, amd_iommu_pci_write_config);
+    if ( amd_iommu == NULL )
+    {
+        PT_LOG("Error: couldn't register amd iommu device\n");
+        return;
+    }
+
+    cfg = (struct amd_iommu_config *)amd_iommu->config;
+
+    pci_config_set_vendor_id((uint8_t *)cfg, PCI_VENDOR_ID_AMD);
+    pci_config_set_device_id((uint8_t *)cfg, PCI_DEVICE_AMD_IOMMU_V2);
+    pci_config_set_class((uint8_t *)cfg, PCI_CLASS_SYSTEM_AMD_IOMMU);
+
+    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;
+}
+
diff --git a/hw/pass-through.h b/hw/pass-through.h
index 884139c..c089987 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -402,6 +402,58 @@ struct pt_reg_info_tbl {
     } u;
 };
 
+#pragma pack(1)
+/* AMD IOMMU v2 support */
+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()
+
 static inline pciaddr_t pt_pci_base_addr(pciaddr_t base)
 {
     if ( base & PCI_ADDRESS_SPACE_IO )
@@ -422,6 +474,6 @@ PCIBus *intel_pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid,
            uint16_t did, const char *name, uint16_t revision);
 void igd_pci_write(PCIDevice *pci_dev, uint32_t config_addr, uint32_t val, int len);
 uint32_t igd_pci_read(PCIDevice *pci_dev, uint32_t config_addr, int len);
-
+void amd_iommu_init(PCIBus *bus);
 #endif /* __PASSTHROUGH_H__ */
 
diff --git a/vl.c b/vl.c
index be8587a..43a0111 100644
--- a/vl.c
+++ b/vl.c
@@ -217,6 +217,7 @@ int cirrus_vga_enabled = 1;
 int std_vga_enabled = 0;
 int vmsvga_enabled = 0;
 int gfx_passthru = 0;
+int guest_iommu = 0;
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
 int graphic_height = 768;
@@ -4295,6 +4296,7 @@ enum {
     QEMU_OPTION_acpi,
     QEMU_OPTION_vcpus,
     QEMU_OPTION_vcpu_avail,
+    QEMU_OPTION_guest_iommu,
 
     /* Debug/Expert options: */
     QEMU_OPTION_serial,
@@ -4468,6 +4470,7 @@ static const QEMUOption qemu_options[] = {
     { "vncunused", 0, QEMU_OPTION_vncunused },
     { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
     { "vcpu_avail", HAS_ARG, QEMU_OPTION_vcpu_avail },
+    { "iommu", 0, QEMU_OPTION_guest_iommu},
 #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
     { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
     { "xen-create", 0, QEMU_OPTION_xen_create },
@@ -5595,6 +5598,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_gfx_passthru:
                 select_vgahw("passthrough");
                 break;
+            case QEMU_OPTION_guest_iommu:
+                guest_iommu = 1;
+                break;
             }
         }
     }

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

             reply	other threads:[~2011-12-14 15:38 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-14 15:38 Wei Wang2 [this message]
2011-12-15 17:33 ` [Qemu-devel] [Xen-devel] [PATCH] xen-qemu: register virtual iommu device on qemu pci bus Ian Jackson
2011-12-15 17:33   ` Ian Jackson
2011-12-16 10:33   ` [Qemu-devel] " Wei Wang2
2011-12-16 10:33     ` Wei Wang2

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=201112141638.05345.wei.wang2@amd.com \
    --to=wei.wang2@amd.com \
    --cc=JBeulich@suse.com \
    --cc=keir@xen.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.