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

[Xen-devel] [PATCH] ioemu-remote&ioemu: support PCI Express Capability Structure version 1.



This patch adds supporting PCI Express Capability Structure version 1
to ioemu-remote and ioemu.


The format of PCI Express Capability Structure is different between
version 1 and version 2.

Current ioemu-remote and ioemu support only version 2. This might
cause conflict with other capability structure if device implement
version 1.

So I created the patch to support version 1 in addition to version 2.


Signed-off-by: Yuji Shimada <shimada-yxb@xxxxxxxxxxxxxxx>

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 51d0a12..6b08441 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -2338,11 +2338,6 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
                 return -1;
         }
 
-        /* always keep the emulate register value to 0,
-         * because hvmloader does not support high MMIO for now.
-         */
-        cfg_entry->data = 0;
-
         /* never mapping the 'empty' upper region,
          * because we'll do it enough for the lower region.
          */

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 51d0a12..9a521c3 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -55,6 +55,10 @@ static uint32_t pt_irqpin_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_bar_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_linkctrl_reg_init(struct pt_dev *ptdev,
+    struct pt_reg_info_tbl *reg, uint32_t real_offset);
+static uint32_t pt_devctrl2_reg_init(struct pt_dev *ptdev,
+    struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,
@@ -75,6 +79,8 @@ static uint8_t pt_msix_size_init(struct pt_dev *ptdev,
     struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
 static uint8_t pt_vendor_size_init(struct pt_dev *ptdev,
     struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
+static uint8_t pt_pcie_size_init(struct pt_dev *ptdev,
+    struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset);
 static int pt_byte_reg_read(struct pt_dev *ptdev,
     struct pt_reg_tbl *cfg_entry,
     uint8_t *valueu, uint8_t valid_mask);
@@ -436,7 +442,7 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
         .init_val   = 0x0000,
         .ro_mask    = 0x0000,
         .emu_mask   = 0xFFFF,
-        .init       = pt_common_reg_init,
+        .init       = pt_linkctrl_reg_init,
         .u.w.read   = pt_word_reg_read,
         .u.w.write  = pt_linkctrl_reg_write,
     },
@@ -447,7 +453,7 @@ static struct pt_reg_info_tbl pt_emu_reg_pcie_tbl[] = {
         .init_val   = 0x0000,
         .ro_mask    = 0x0000,
         .emu_mask   = 0xFFFF,
-        .init       = pt_common_reg_init,
+        .init       = pt_devctrl2_reg_init,
         .u.w.read   = pt_word_reg_read,
         .u.w.write  = pt_devctrl2_reg_write,
     },
@@ -664,8 +670,8 @@ static const struct pt_reg_grp_info_tbl 
pt_emu_reg_grp_tbl[] = {
     {
         .grp_id     = PCI_CAP_ID_EXP,
         .grp_type   = GRP_TYPE_EMU,
-        .grp_size   = 0x3C,
-        .size_init  = pt_reg_grp_size_init,
+        .grp_size   = 0xFF,
+        .size_init  = pt_pcie_size_init,
         .emu_reg_tbl= pt_emu_reg_pcie_tbl,
     },
     /* MSI-X Capability Structure reg group */
@@ -1867,12 +1873,57 @@ static uint32_t pt_bar_reg_init(struct pt_dev *ptdev,
     return reg_field;
 }
 
+/* initialize Link Control register */
+static uint32_t pt_linkctrl_reg_init(struct pt_dev *ptdev,
+        struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+    uint8_t cap_ver = 0;
+    uint8_t dev_type = 0;
+
+    cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+        (uint8_t)PCI_EXP_FLAGS_VERS);
+    dev_type = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] 
&
+        (uint8_t)PCI_EXP_FLAGS_TYPE) >> 4;
+    
+    /* no need to initialize in case of Root Complex Integrated Endpoint
+     * with cap_ver 1.x 
+     */
+    if ((dev_type == PCI_EXP_TYPE_ROOT_INT_EP) && (cap_ver == 1))
+        return PT_INVALID_REG;
+
+    return reg->init_val;
+}
+
+/* initialize Device Control 2 register */
+static uint32_t pt_devctrl2_reg_init(struct pt_dev *ptdev,
+        struct pt_reg_info_tbl *reg, uint32_t real_offset)
+{
+    uint8_t cap_ver = 0;
+
+    cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+        (uint8_t)PCI_EXP_FLAGS_VERS);
+    
+    /* no need to initialize in case of cap_ver 1.x */
+    if (cap_ver == 1)
+        return PT_INVALID_REG;
+
+    return reg->init_val;
+}
+
 /* initialize Link Control 2 register */
 static uint32_t pt_linkctrl2_reg_init(struct pt_dev *ptdev,
         struct pt_reg_info_tbl *reg, uint32_t real_offset)
 {
     int reg_field = 0;
+    uint8_t cap_ver = 0;
 
+    cap_ver = (ptdev->dev.config[(real_offset - reg->offset) + PCI_EXP_FLAGS] &
+        (uint8_t)PCI_EXP_FLAGS_VERS);
+    
+    /* no need to initialize in case of cap_ver 1.x */
+    if (cap_ver == 1)
+        return PT_INVALID_REG;
+    
     /* set Supported Link Speed */
     reg_field |= 
         (0x0F & 
@@ -2034,6 +2085,91 @@ static uint8_t pt_vendor_size_init(struct pt_dev *ptdev,
     return ptdev->dev.config[base_offset + 0x02];
 }
 
+/* get PCI Express Capability Structure register group size */
+static uint8_t pt_pcie_size_init(struct pt_dev *ptdev,
+        struct pt_reg_grp_info_tbl *grp_reg, uint32_t base_offset)
+{
+    PCIDevice *d = &ptdev->dev;
+    uint16_t exp_flag = 0;
+    uint16_t type = 0;
+    uint16_t vers = 0;
+    uint8_t pcie_size = 0;
+
+    exp_flag = *((uint16_t*)(d->config + (base_offset + PCI_EXP_FLAGS)));
+    type = (exp_flag & PCI_EXP_FLAGS_TYPE) >> 4;
+    vers = (exp_flag & PCI_EXP_FLAGS_VERS);
+
+    /* calculate size depend on capability version and device/port type */
+    /* in case of PCI Express Base Specification Rev 1.x */
+    if (vers == 1)
+    {
+        /* The PCI Express Capabilities, Device Capabilities, and Device 
+         * Status/Control registers are required for all PCI Express devices. 
+         * The Link Capabilities and Link Status/Control are required for all 
+         * Endpoints that are not Root Complex Integrated Endpoints. Endpoints 
+         * are not required to implement registers other than those listed 
+         * above and terminate the capability structure.
+         */
+        switch (type) {
+        case PCI_EXP_TYPE_ENDPOINT:
+        case PCI_EXP_TYPE_LEG_END:
+            pcie_size = 0x14;
+            break;
+        case PCI_EXP_TYPE_ROOT_INT_EP:
+            /* has no link */
+            pcie_size = 0x0C;
+            break;
+        /* only EndPoint passthrough is supported */
+        case PCI_EXP_TYPE_ROOT_PORT:
+        case PCI_EXP_TYPE_UPSTREAM:
+        case PCI_EXP_TYPE_DOWNSTREAM:
+        case PCI_EXP_TYPE_PCI_BRIDGE:
+        case PCI_EXP_TYPE_PCIE_BRIDGE:
+        case PCI_EXP_TYPE_ROOT_EC:
+        default:
+            /* exit I/O emulator */
+            PT_LOG("Internal error: Unsupported device/port type[%d]. "
+                "I/O emulator exit.\n", type);
+            exit(1);
+        }
+    }
+    /* in case of PCI Express Base Specification Rev 2.0 */
+    else if (vers == 2)
+    {
+        switch (type) {
+        case PCI_EXP_TYPE_ENDPOINT:
+        case PCI_EXP_TYPE_LEG_END:
+        case PCI_EXP_TYPE_ROOT_INT_EP:
+            /* For Functions that do not implement the registers, 
+             * these spaces must be hardwired to 0b.
+             */
+            pcie_size = 0x3C;
+            break;
+        /* only EndPoint passthrough is supported */
+        case PCI_EXP_TYPE_ROOT_PORT:
+        case PCI_EXP_TYPE_UPSTREAM:
+        case PCI_EXP_TYPE_DOWNSTREAM:
+        case PCI_EXP_TYPE_PCI_BRIDGE:
+        case PCI_EXP_TYPE_PCIE_BRIDGE:
+        case PCI_EXP_TYPE_ROOT_EC:
+        default:
+            /* exit I/O emulator */
+            PT_LOG("Internal error: Unsupported device/port type[%d]. "
+                "I/O emulator exit.\n", type);
+            exit(1);
+        }
+    }
+    else
+    {
+        /* exit I/O emulator */
+        PT_LOG("Internal error: Unsupported capability version[%d]. "
+            "I/O emulator exit.\n", vers);
+        exit(1);
+    }
+
+    return pcie_size;
+}
+
 /* read byte size emulate register */
 static int pt_byte_reg_read(struct pt_dev *ptdev,
         struct pt_reg_tbl *cfg_entry,
diff --git a/hw/pass-through.h b/hw/pass-through.h
index 2175c93..bc3ef8c 100644
--- a/hw/pass-through.h
+++ b/hw/pass-through.h
@@ -64,6 +64,21 @@
 #define PCI_MSI_FLAGS_MASK_BIT  0x0100
 #endif
 
+#ifndef PCI_EXP_TYPE_PCIE_BRIDGE
+/* PCI/PCI-X to PCIE Bridge */
+#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8
+#endif
+
+#ifndef PCI_EXP_TYPE_ROOT_INT_EP
+/* Root Complex Integrated Endpoint */
+#define PCI_EXP_TYPE_ROOT_INT_EP 0x9
+#endif
+
+#ifndef PCI_EXP_TYPE_ROOT_EC
+/* Root Complex Event Collector */
+#define PCI_EXP_TYPE_ROOT_EC     0xa
+#endif
+
 #define PT_INVALID_REG          0xFFFFFFFF      /* invalid register value */
 #define PT_BAR_ALLF             0xFFFFFFFF      /* BAR ALLF value */
 #define PT_BAR_MEM_RO_MASK      0x0000000F      /* BAR ReadOnly mask(Memory) *



_______________________________________________
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®.