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

[Xen-changelog] [qemu-xen-unstable] passthrough: pt_bar_mapping etc.: use correct CMD for PCI BAR mapping etc.



commit 5d767b7b3fac52336f59e5b40d8befa6b1909937
Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Date:   Tue May 5 15:22:17 2009 +0100

    passthrough: pt_bar_mapping etc.: use correct CMD for PCI BAR mapping etc.
    
    dbb8aafa702b8b4f5568e08641d98471fd04e0f8 has a bug:
    The virtual CMD value we get from reg_entry->data is not the proper
    value because reg_entry->data only holds the emulated bits and the
    PCI_COMMAND_IO/PCI_COMMAND_MEMORY bits are not in it.  Instead, we can
    use pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2) to get the proper
    value.
    
    We should only update the mapping of the related BAR, NOT the mappings
    of ALL BARs.
    
    In pt_exp_rom_bar_reg_write(), we should also update the mapping. And
    for PCI_ROM_SLOT, when the PCI_ROM_ADDRESS_ENABLE bit is 0, we should
    not have the mapping.
    
    Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 hw/pass-through.c |  113 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 63 insertions(+), 50 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 6a53137..d2bed51 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -1791,64 +1791,74 @@ out:
 }
 
 /* mapping BAR */
-static void pt_bar_mapping(struct pt_dev *ptdev, int io_enable, int mem_enable)
+static void pt_bar_mapping_one(struct pt_dev *ptdev, int bar, int io_enable,
+    int mem_enable)
 {
     PCIDevice *dev = (PCIDevice *)&ptdev->dev;
     PCIIORegion *r;
     struct pt_region *base = NULL;
     uint32_t r_size = 0, r_addr = -1;
     int ret = 0;
-    int i;
 
-    for (i=0; i<PCI_NUM_REGIONS; i++)
-    {
-        r = &dev->io_regions[i];
+    r = &dev->io_regions[bar];
 
-        /* check valid region */
-        if (!r->size)
-            continue;
+    /* check valid region */
+    if (!r->size)
+        return;
 
-        base = &ptdev->bases[i];
-        /* skip unused BAR or upper 64bit BAR */
-        if ((base->bar_flag == PT_BAR_FLAG_UNUSED) ||
-           (base->bar_flag == PT_BAR_FLAG_UPPER))
-               continue;
+    base = &ptdev->bases[bar];
+    /* skip unused BAR or upper 64bit BAR */
+    if ((base->bar_flag == PT_BAR_FLAG_UNUSED) ||
+       (base->bar_flag == PT_BAR_FLAG_UPPER))
+           return;
 
-        /* copy region address to temporary */
-        r_addr = r->addr;
+    /* copy region address to temporary */
+    r_addr = r->addr;
 
-        /* need unmapping in case I/O Space or Memory Space disable */
-        if (((base->bar_flag == PT_BAR_FLAG_IO) && !io_enable ) ||
-            ((base->bar_flag == PT_BAR_FLAG_MEM) && !mem_enable ))
+    /* need unmapping in case I/O Space or Memory Space disable */
+    if (((base->bar_flag == PT_BAR_FLAG_IO) && !io_enable ) ||
+        ((base->bar_flag == PT_BAR_FLAG_MEM) && !mem_enable ))
+        r_addr = -1;
+    if ( (bar == PCI_ROM_SLOT) && (r_addr != -1) )
+    {
+        uint32_t rom_reg;
+        rom_reg = pt_pci_read_config(&ptdev->dev, PCI_ROM_ADDRESS, 4);
+        if ( !(rom_reg & PCI_ROM_ADDRESS_ENABLE) )
             r_addr = -1;
+    }
 
-        /* prevent guest software mapping memory resource to 00000000h */
-        if ((base->bar_flag == PT_BAR_FLAG_MEM) && (r_addr == 0))
-            r_addr = -1;
+    /* prevent guest software mapping memory resource to 00000000h */
+    if ((base->bar_flag == PT_BAR_FLAG_MEM) && (r_addr == 0))
+        r_addr = -1;
 
-        /* align resource size (memory type only) */
-        r_size = r->size;
-        PT_GET_EMUL_SIZE(base->bar_flag, r_size);
-
-        /* check overlapped address */
-        ret = pt_chk_bar_overlap(dev->bus, dev->devfn,
-                        r_addr, r_size, r->type);
-        if (ret > 0)
-            PT_LOG("Warning: ptdev[%02x:%02x.%x][Region:%d][Address:%08xh]"
-                "[Size:%08xh] is overlapped.\n", pci_bus_num(dev->bus),
-                (dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7),
-                i, r_addr, r_size);
-
-        /* check whether we need to update the mapping or not */
-        if (r_addr != ptdev->bases[i].e_physbase)
-        {
-            /* mapping BAR */
-            r->map_func((PCIDevice *)ptdev, i, r_addr,
-                         r_size, r->type);
-        }
+    /* align resource size (memory type only) */
+    r_size = r->size;
+    PT_GET_EMUL_SIZE(base->bar_flag, r_size);
+
+    /* check overlapped address */
+    ret = pt_chk_bar_overlap(dev->bus, dev->devfn,
+                    r_addr, r_size, r->type);
+    if (ret > 0)
+        PT_LOG("Warning: ptdev[%02x:%02x.%x][Region:%d][Address:%08xh]"
+            "[Size:%08xh] is overlapped.\n", pci_bus_num(dev->bus),
+            (dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7),
+            bar, r_addr, r_size);
+
+    /* check whether we need to update the mapping or not */
+    if (r_addr != ptdev->bases[bar].e_physbase)
+    {
+        /* mapping BAR */
+        r->map_func((PCIDevice *)ptdev, bar, r_addr,
+                     r_size, r->type);
     }
+}
 
-    return;
+static void pt_bar_mapping(struct pt_dev *ptdev, int io_enable, int mem_enable)
+{
+    int i;
+
+    for (i=0; i<PCI_NUM_REGIONS; i++)
+        pt_bar_mapping_one(ptdev, i, io_enable, mem_enable);
 }
 
 /* check power state transition */
@@ -3051,6 +3061,7 @@ static int pt_bar_reg_write(struct pt_dev *ptdev,
     uint32_t prev_offset;
     uint32_t r_size = 0;
     int index = 0;
+    uint16_t cmd;
 
     /* get BAR index */
     index = pt_bar_offset_to_index(reg->offset);
@@ -3170,14 +3181,10 @@ exit:
     *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
 
     /* After BAR reg update, we need to remap BAR*/
-    reg_grp_entry = pt_find_reg_grp(ptdev, PCI_COMMAND);
-    if (reg_grp_entry)
-    {
-        reg_entry = pt_find_reg(reg_grp_entry, PCI_COMMAND);
-        if (reg_entry)
-            pt_bar_mapping(ptdev, reg_entry->data & PCI_COMMAND_IO,
-                                  reg_entry->data & PCI_COMMAND_MEMORY);
-    }
+    cmd = pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2);
+    pt_bar_mapping_one(ptdev, index, cmd & PCI_COMMAND_IO,
+        cmd & PCI_COMMAND_MEMORY);
+
     return 0;
 }
 
@@ -3195,6 +3202,7 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
     uint32_t r_size = 0;
     uint32_t bar_emu_mask = 0;
     uint32_t bar_ro_mask = 0;
+    uint16_t cmd;
 
     r = &d->io_regions[PCI_ROM_SLOT];
     r_size = r->size;
@@ -3217,6 +3225,11 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev,
     throughable_mask = ~bar_emu_mask & valid_mask;
     *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask);
 
+    /* After BAR reg update, we need to remap BAR*/
+    cmd = pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2);
+    pt_bar_mapping_one(ptdev, PCI_ROM_SLOT, cmd & PCI_COMMAND_IO,
+        cmd & PCI_COMMAND_MEMORY);
+
     return 0;
 }
 
--
generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git

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


 


Rackspace

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