[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC] [PATCH 2/2] ioemu: fix up some issues for PCI passthrough with stub domain



This patch fixes up the following issues for enabling PCI passthrough 
with stub domain.

- Reading and writing a data to/from device register with 
  pci_{read/write}_block, byte swap occurs.
- Can't get a BAR in pt_libpci_fixup. 
- Don't get PCI Vendor ID, Device ID and Device Class for PCI passthrough 
device.

Thanks,
--
Shohei Fujiwara


Signed-off-by: Shohei Fujiwara <fujiwara-sxa@xxxxxxxxxxxxxxx>

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 4a86309..6373227 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -1104,6 +1104,58 @@ out:
     return index;
 }
 
+static int pt_pci_write_block(struct pci_dev *d, int pos, uint32_t *val,
+                              int len)
+{
+    int ret = 0;
+
+    switch (len)
+    {
+    case 1:
+        ret = pci_write_byte(d, pos, *(uint8_t *)val);
+        break;
+    case 2:
+        ret = pci_write_word(d, pos, *(uint16_t *)val);
+        break;
+    case 4:
+        ret = pci_write_long(d, pos, *val);
+        break;
+    }
+    return ret;
+}
+
+static int pt_pci_read_block(struct pci_dev *d, int pos, uint32_t *val,
+                             int len)
+{
+    uint32_t valid_mask = 0xffffffff;
+    int ret = 1;
+
+    switch (len)
+    {
+    case 1:
+        *val = (uint32_t)pci_read_byte(d, pos);
+        break;
+    case 2:
+        *val = (uint32_t)pci_read_word(d, pos);
+        break;
+    case 4:
+        *val = pci_read_long(d, pos);
+        break;
+    default:
+        ret = 0;
+        break;
+    }
+
+    if (ret)
+    {
+        valid_mask = (0xffffffff >> ((4 - len) << 3));
+        if ((*val & valid_mask) == valid_mask)
+            ret = 0;
+    }
+
+    return ret;
+}
+
 static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val,
                                 int len)
 {
@@ -1195,7 +1247,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t 
address, uint32_t val,
     }
 
     /* read I/O device register value */
-    ret = pci_read_block(pci_dev, address, (uint8_t *)&read_val, len);
+    ret = pt_pci_read_block(pci_dev, address, &read_val, len);
 
     if (!ret)
     {
@@ -1281,7 +1333,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t 
address, uint32_t val,
     val >>= ((address & 3) << 3);
 
 out:
-    ret = pci_write_block(pci_dev, address, (uint8_t *)&val, len);
+    ret = pt_pci_write_block(pci_dev, address, &val, len);
 
     if (!ret)
         PT_LOG("Error: pci_write_block failed. return value[%d].\n", ret);
@@ -1364,7 +1416,7 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t 
address, int len)
     }
 
     /* read I/O device register value */
-    ret = pci_read_block(pci_dev, address, (uint8_t *)&val, len);
+    ret = pt_pci_read_block(pci_dev, address, &val, len);
 
     if (!ret)
     {
@@ -1461,6 +1513,7 @@ exit:
 static void pt_libpci_fixup(struct pci_dev *dev)
 {
 #if !defined(PCI_LIB_VERSION) || PCI_LIB_VERSION < 0x030100
+#ifndef CONFIG_STUBDOM
     int i;
     FILE *fp;
     char path[PATH_MAX], buf[256];
@@ -1492,6 +1545,30 @@ static void pt_libpci_fixup(struct pci_dev *dev)
     }
 
     fclose(fp);
+#else
+    uint32_t    value = 0;
+    int i;
+
+    for ( i = 0; i < PCI_NUM_REGIONS; i++ )
+    {
+        value = pci_read_long(dev, PCI_BASE_ADDRESS_0 + i*4);
+        if ( i < PCI_ROM_SLOT )
+        {
+            dev->base_addr[i] |= (value & 0x0f);
+        }
+        else
+        {
+            dev->rom_base_addr |= (value & 0x0f);
+        }
+
+        if ((value & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
+            == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64) )
+        {
+          i++;
+        }
+    }
+
+#endif /* !CONFIG_STUBDOM */
 #endif /* PCI_LIB_VERSION < 0x030100 */
 }
 
@@ -3582,7 +3659,12 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
         PT_LOG("Error: couldn't locate device in libpci structures\n");
         return NULL;
     }
+#ifndef CONFIG_STUBDOM
     pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | 
PCI_FILL_SIZES);
+#else
+    pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE 
+                           | PCI_FILL_SIZES | PCI_FILL_IDENT | PCI_FILL_CLASS);
+#endif
     pt_libpci_fixup(pci_dev);
 
     if ( e_devfn == PT_VIRT_DEVFN_AUTO ) {
@@ -3711,9 +3793,16 @@ struct pt_dev * register_real_device(PCIBus *e_bus,
     }
 
 out:
+#ifndef CONFIG_STUBDOM
     PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n"
            "IRQ type = %s\n", r_bus, r_dev, r_func,
            assigned_device->msi_trans_en? "MSI-INTx":"INTx");
+#else
+    PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n",
+           r_bus, r_dev, r_func);
+    PT_LOG("IRQ type = %s\n", 
+           assigned_device->msi_trans_en? "MSI-INTx":"INTx");
+#endif
 
     return assigned_device;
 }




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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.