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

[Xen-devel] [PATCH] ioemu: Fix MSI/MSI-X capability structure virtualization code



This patch fixes MSI/MSI-X capability structure virtualization code.

Currently, xen does not support multiple message (multiple vector).
So multiple message capable field should be emulated and fixed to 0
(single vector).

With the patch, my FC-HBA works when I assign it to guest domain where
windows 2008 runs.


In addition to this, initial values of emulated registers should be
the same with initial values defined in PCI spec. If initial values
are not defined, they should be 0. The emulated field mask and
read-only field mask are also fixed.

Thanks,
--
Yuji Shimada


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

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 308bcc3..487b08d 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -73,8 +73,6 @@ 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,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
-static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,
-    struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,
     struct pt_reg_info_tbl *reg, uint32_t real_offset);
 static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,
@@ -552,8 +550,8 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
         .offset     = PCI_MSI_FLAGS, // 2
         .size       = 2,
         .init_val   = 0x0000,
-        .ro_mask    = 0x018E,
-        .emu_mask   = 0xFFFF,
+        .ro_mask    = 0xFF8E,
+        .emu_mask   = 0x007F,
         .init       = pt_msgctrl_reg_init,
         .u.w.read   = pt_word_reg_read,
         .u.w.write  = pt_msgctrl_reg_write,
@@ -564,9 +562,9 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
         .offset     = PCI_MSI_ADDRESS_LO, // 4
         .size       = 4,
         .init_val   = 0x00000000,
-        .ro_mask    = 0x00000FF0,    /* bit 4~11 is reserved for MSI in x86 */
+        .ro_mask    = 0x00000003,
         .emu_mask   = 0xFFFFFFFF,
-        .init       = pt_msgaddr32_reg_init,
+        .init       = pt_common_reg_init,
         .u.dw.read  = pt_long_reg_read,
         .u.dw.write = pt_msgaddr32_reg_write,
         .u.dw.restore = NULL,
@@ -588,7 +586,7 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
         .offset     = PCI_MSI_DATA_32, // 8
         .size       = 2,
         .init_val   = 0x0000,
-        .ro_mask    = 0x3800,
+        .ro_mask    = 0x0000,
         .emu_mask   = 0xFFFF,
         .init       = pt_msgdata_reg_init,
         .u.w.read   = pt_word_reg_read,
@@ -600,7 +598,7 @@ static struct pt_reg_info_tbl pt_emu_reg_msi_tbl[] = {
         .offset     = PCI_MSI_DATA_64, // 12
         .size       = 2,
         .init_val   = 0x0000,
-        .ro_mask    = 0x3800,
+        .ro_mask    = 0x0000,
         .emu_mask   = 0xFFFF,
         .init       = pt_msgdata_reg_init,
         .u.w.read   = pt_word_reg_read,
@@ -2456,7 +2454,7 @@ static uint32_t pt_msgctrl_reg_init(struct pt_dev *ptdev,
     uint32_t reg_field = 0;
 
     /* use I/O device register's value as initial value */
-    reg_field |= *((uint16_t*)(d->config + real_offset));
+    reg_field = *((uint16_t*)(d->config + real_offset));
 
     if (reg_field & PCI_MSI_FLAGS_ENABLE)
     {
@@ -2466,40 +2464,18 @@ static uint32_t pt_msgctrl_reg_init(struct pt_dev 
*ptdev,
     ptdev->msi->flags |= (reg_field | MSI_FLAG_UNINIT);
     ptdev->msi->ctrl_offset = real_offset;
 
-    /* All register is 0 after reset, except first 4 byte */
-    reg_field &= reg->ro_mask;
-
-    return reg_field;
-}
-
-/* initialize Message Address register */
-static uint32_t pt_msgaddr32_reg_init(struct pt_dev *ptdev,
-        struct pt_reg_info_tbl *reg, uint32_t real_offset)
-{
-    PCIDevice *d = (struct PCIDevice *)ptdev;
-    uint32_t reg_field = 0;
-
-    /* use I/O device register's value as initial value */
-    reg_field |= *((uint32_t*)(d->config + real_offset));
-
-    return reg_field;
+    return reg->init_val;
 }
 
 /* initialize Message Upper Address register */
 static uint32_t pt_msgaddr64_reg_init(struct pt_dev *ptdev,
         struct pt_reg_info_tbl *reg, uint32_t real_offset)
 {
-    PCIDevice *d = (struct PCIDevice *)ptdev;
-    uint32_t reg_field = 0;
-
     /* no need to initialize in case of 32 bit type */
     if (!(ptdev->msi->flags & PCI_MSI_FLAGS_64BIT))
         return PT_INVALID_REG;
 
-    /* use I/O device register's value as initial value */
-    reg_field |= *((uint32_t*)(d->config + real_offset));
-
-    return reg_field;
+    return reg->init_val;
 }
 
 /* this function will be called twice (for 32 bit and 64 bit type) */
@@ -2507,14 +2483,13 @@ static uint32_t pt_msgaddr64_reg_init(struct pt_dev 
*ptdev,
 static uint32_t pt_msgdata_reg_init(struct pt_dev *ptdev,
         struct pt_reg_info_tbl *reg, uint32_t real_offset)
 {
-    PCIDevice *d = (struct PCIDevice *)ptdev;
     uint32_t flags = ptdev->msi->flags;
     uint32_t offset = reg->offset;
 
     /* check the offset whether matches the type or not */
     if (((offset == PCI_MSI_DATA_64) &&  (flags & PCI_MSI_FLAGS_64BIT)) ||
         ((offset == PCI_MSI_DATA_32) && !(flags & PCI_MSI_FLAGS_64BIT)))
-        return *((uint16_t*)(d->config + real_offset));
+        return reg->init_val;
     else
         return PT_INVALID_REG;
 }
@@ -2528,18 +2503,17 @@ static uint32_t pt_msixctrl_reg_init(struct pt_dev 
*ptdev,
     uint16_t reg_field = 0;
 
     /* use I/O device register's value as initial value */
-    reg_field |= *((uint16_t*)(d->config + real_offset));
+    reg_field = *((uint16_t*)(d->config + real_offset));
 
     if (reg_field & PCI_MSIX_ENABLE)
     {
         PT_LOG("MSIX enabled already, disable first\n");
         pci_write_word(pdev, real_offset, reg_field & ~PCI_MSIX_ENABLE);
-        reg_field &= ~(PCI_MSIX_ENABLE | PCI_MSIX_MASK);
     }
 
     ptdev->msix->ctrl_offset = real_offset;
 
-    return reg_field;
+    return reg->init_val;
 }
 
 /* get register group size */


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