qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/6] New service functions and ported old functions


From: Alexey Korolev
Subject: [Qemu-devel] [PATCH 2/6] New service functions and ported old functions to 64bit
Date: Thu, 1 Mar 2012 19:15:40 +1300

This patch is all about service functions
It includes: 
- basic operations with lists
- 64bit modification of Pci_size_roundup()
- modification of pci_bios_get_bar to support HUGE bars (size over 4GB)
- 2 service function to get pci_region statistics
- dump entry - for debug output

Signed-off-by: Alexey Korolev <address@hidden>
---
 src/pciinit.c |  132 +++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 91 insertions(+), 41 deletions(-)

diff --git a/src/pciinit.c b/src/pciinit.c
index 2e5416c..dbfa4f2 100644
--- a/src/pciinit.c
+++ b/src/pciinit.c
@@ -51,33 +51,30 @@ struct pci_region {
     u64 base;
 };
 
-static int pci_size_to_index(u32 size, enum pci_region_type type)
-{
-    int index = __fls(size);
-    int shift = (type == PCI_REGION_TYPE_IO) ?
-        PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
-
-    if (index < shift)
-        index = shift;
-    index -= shift;
-    return index;
-}
+#define foreach_region_entry(R, ENTRY)    \
+    for (ENTRY = (R)->list; ENTRY; ENTRY = ENTRY->next)
 
-static u32 pci_index_to_size(int index, enum pci_region_type type)
-{
-    int shift = (type == PCI_REGION_TYPE_IO) ?
-        PCI_IO_INDEX_SHIFT : PCI_MEM_INDEX_SHIFT;
+#define foreach_region_entry_safe(R, N, ENTRY)    \
+        for (ENTRY = (R)->list; ENTRY && ({N=ENTRY->next; 1;}); \
+            ENTRY = N)
 
-    return 0x1 << (index + shift);
+static inline void region_entry_del(struct pci_region_entry *entry)
+{
+    struct pci_region_entry *next = entry->next;
+    *entry->pprev = next;
+    if (next)
+        next->pprev = entry->pprev;
 }
 
-static enum pci_region_type pci_addr_to_type(u32 addr)
+static inline void
+region_entry_add(struct pci_region *r, struct pci_region_entry *entry)
 {
-    if (addr & PCI_BASE_ADDRESS_SPACE_IO)
-        return PCI_REGION_TYPE_IO;
-    if (addr & PCI_BASE_ADDRESS_MEM_PREFETCH)
-        return PCI_REGION_TYPE_PREFMEM;
-    return PCI_REGION_TYPE_MEM;
+    struct pci_region_entry *first = r->list;
+    entry->next = first;
+    if (first)
+        first->pprev = &entry->next;
+    r->list = entry;
+    entry->pprev = &r->list;
 }
 
 static u32 pci_bar(struct pci_device *pci, int region_num)
@@ -324,38 +321,91 @@ pci_bios_init_bus(void)
     pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
 }
 
-
 /****************************************************************
  * Bus sizing
  ****************************************************************/
 
-static u32 pci_size_roundup(u32 size)
+static u64 pci_size_roundup(u64 size)
 {
-    int index = __fls(size-1)+1;
-    return 0x1 << index;
+    int index = __fls((u32)((size - 1) >> 32));
+    if (!index)
+       index = __fls((u32)(size - 1));
+    return 0x1 << (index + 1);
 }
 
-static void
-pci_bios_get_bar(struct pci_device *pci, int bar, u32 *val, u32 *size)
+static u64
+pci_get_bar_size(struct pci_device *pci, int bar,
+                      enum pci_region_type *type, int *is64bit)
 {
     u32 ofs = pci_bar(pci, bar);
     u16 bdf = pci->bdf;
-    u32 old = pci_config_readl(bdf, ofs);
-    u32 mask;
-
-    if (bar == PCI_ROM_SLOT) {
-        mask = PCI_ROM_ADDRESS_MASK;
-        pci_config_writel(bdf, ofs, mask);
+    u32 l, sz, mask;
+
+    mask = (bar == PCI_ROM_SLOT) ? PCI_ROM_ADDRESS_MASK : ~0;
+    l = pci_config_readl(bdf, ofs);
+    pci_config_writel(bdf, ofs, mask);
+    sz = pci_config_readl(bdf, ofs);
+    pci_config_writel(bdf, ofs, l);
+
+    *is64bit = 0;
+    if (l & PCI_BASE_ADDRESS_SPACE_IO) {
+        mask = PCI_BASE_ADDRESS_IO_MASK;
+        *type = PCI_REGION_TYPE_IO;
     } else {
-        if (old & PCI_BASE_ADDRESS_SPACE_IO)
-            mask = PCI_BASE_ADDRESS_IO_MASK;
+        mask = PCI_BASE_ADDRESS_MEM_MASK;
+        if (l & PCI_BASE_ADDRESS_MEM_TYPE_64)
+            *is64bit = 1;
+        if (l & PCI_BASE_ADDRESS_MEM_PREFETCH)
+            *type = PCI_REGION_TYPE_PREFMEM;
         else
-            mask = PCI_BASE_ADDRESS_MEM_MASK;
-        pci_config_writel(bdf, ofs, ~0);
+            *type = PCI_REGION_TYPE_MEM;
+    }
+    if (*is64bit) {
+        u64 mask64, sz64 = sz;
+        l = pci_config_readl(bdf, ofs + 4);
+        pci_config_writel(bdf, ofs + 4, ~0);
+        sz = pci_config_readl(bdf, ofs + 4);
+        pci_config_writel(bdf, ofs + 4, l);
+        mask64 = mask | ((u64)0xffffffff << 32);
+        sz64 |= ((u64)sz << 32);
+        return (~(sz64 & mask64)) + 1;
+    }
+    return (u32)((~(sz & mask)) + 1);
+}
+
+static u64 pci_region_max_size(struct pci_region *r)
+{
+    u64 max = 0;
+    struct pci_region_entry *entry;
+    foreach_region_entry(r, entry) {
+        max = (max > entry->size) ? max : entry->size;
+    }
+    return max;
+}
+
+static u64 pci_region_sum(struct pci_region *r)
+{
+    u64 sum = 0;
+    struct pci_region_entry *entry;
+    foreach_region_entry(r, entry) {
+        sum += entry->size;
     }
-    *val = pci_config_readl(bdf, ofs);
-    pci_config_writel(bdf, ofs, old);
-    *size = (~(*val & mask)) + 1;
+    return sum;
+}
+
+static void
+dump_entry(struct pci_region_entry *entry)
+{
+    if (entry->this_region )
+        dprintf(1, "PCI bus %d (secondary)", entry->dev->secondary_bus);
+    else
+        dprintf(1, "PCI region entry: bdf=%02x:%02x.%x BAR %d",
+              pci_bdf_to_bus(entry->dev->bdf), pci_bdf_to_dev(entry->dev->bdf),
+              pci_bdf_to_fn(entry->dev->bdf), entry->bar);
+    dprintf(1, " base=0x%08x%08x size=0x%08x%08x [%s, %s]\n",
+        (u32)(entry->base>>32), (u32)entry->base,
+        (u32)(entry->size>>32), (u32)entry->size,
+        region_type_name[entry->type],entry->is64bit ? "64bits" : "32bits");
 }
 
 static void pci_bios_bus_reserve(struct pci_bus *bus, int type, u32 size)
-- 
1.7.5.4





reply via email to

[Prev in Thread] Current Thread [Next in Thread]