Skip to contentSkip to conversation

xen-qemu: register virtual iommu device on qemu pci bus

PATCH In review Wei Wang2 2 participants 3 messages Dec 14, 2011 – Dec 16, 2011

lore
Share & tools
lore

Wei Wang2

author
#0 lore raw

PATCH 1/1 xen-qemu: register virtual iommu device on qemu pci bus

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

hw/pass-through.c +89 -0
index 919937f..d6f35d8 100644
@@ -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;
+}
+
hw/pass-through.h +53 -1

65 lines not on this page · raw message

vl.c +6 -0
index be8587a..43a0111 100644
@@ -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;
             }
         }
     }

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#1 lore raw

Wei Wang2 writes ("[Xen-devel] [PATCH] xen-qemu: register virtual iommu device on qemu pci bus"):

Quoted 2 lines

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 for this submission.

However, we are trying to focus development on the new xen-supporting upstream qemu branches.

This old qemu branch is basically dead. We will have to give it bugfixes and security fixes, it in parallel with the new trees, for a long time (because old guests may need it). So for that reason I would really prefer not to add new features to it.

Would you be able to rebase your work on the upstream qemu ? You will need Anthony Perard's PCI passthrough series of course, and you will also need to liase with qemu upstream (so I've CC'd their list) since it will be their tree that you'll be targeting.

If there is a particular reason why this work should be in qemu-xen-unstable then please do say. I'm open to being persuaded.

Thanks,
Ian.

author
#2 lore raw
Quoted 1 line · On Thursday 15 December 2011 18:33:33 Ian Jackson wrote:

Wei Wang2 writes ("[Xen-devel] [PATCH] xen-qemu: register virtual iommu

device on qemu pci bus"):

Quoted 18 lines
Quoted 2 lines

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 for this submission.

However, we are trying to focus development on the new xen-supporting upstream qemu branches.

This old qemu branch is basically dead. We will have to give it bugfixes and security fixes, it in parallel with the new trees, for a long time (because old guests may need it). So for that reason I would really prefer not to add new features to it.

Would you be able to rebase your work on the upstream qemu ? You will need Anthony Perard's PCI passthrough series of course, and you will also need to liase with qemu upstream (so I've CC'd their list) since it will be their tree that you'll be targeting.

Quoted 5 lines

If there is a particular reason why this work should be in qemu-xen-unstable then please do say. I'm open to being persuaded.

Thanks,
Ian.

Sure, I will do that. Thanks for the suggestion
Wei.