[kvm-unit-tests PATCH 04/14] pci: refactor init process to pci_dev_init()

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

 



pci_find_dev() is not sufficient for further tests for Intel IOMMU. This
patch introduced pci_dev struct, as a abstract of a specific PCI device.

All the rest of current PCI APIs are changed to leverage the pci_dev
struct.

x86/vmexit.c is the only user of the old PCI APIs. Changing it to use
the new ones.

(Indentation is fixed from using 4 spaces into tab in pci.c)

Signed-off-by: Peter Xu <peterx@xxxxxxxxxx>
---
 lib/pci.c    | 75 +++++++++++++++++++++++++++++++++++++++++-------------------
 lib/pci.h    | 29 ++++++++++++++++++-----
 x86/vmexit.c | 22 ++++--------------
 3 files changed, 80 insertions(+), 46 deletions(-)

diff --git a/lib/pci.c b/lib/pci.c
index 0058d70..ef0b02a 100644
--- a/lib/pci.c
+++ b/lib/pci.c
@@ -7,37 +7,66 @@
 #include "pci.h"
 #include "asm/pci.h"
 
-/* Scan bus look for a specific device. Only bus 0 scanned for now. */
-pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id)
+/*
+ * Scan bus look for a specific device. Only bus 0 scanned for now.
+ * After the scan, a pci_dev is returned with correct BAR information.
+ */
+int pci_dev_init(pci_dev *dev, uint16_t vendor_id, uint16_t device_id)
+{
+	unsigned i;
+	uint32_t id;
+
+	memset(dev, 0, sizeof(*dev));
+
+	for (i = 0; i < PCI_DEVFN_MAX; ++i) {
+		id = pci_config_read(i, 0);
+		if ((id & 0xFFFF) == vendor_id && (id >> 16) == device_id)
+			break;
+	}
+
+	if (i == PCI_DEVFN_MAX) {
+		printf("PCI: failed init dev (vendor: 0x%04x, "
+		       "device: 0x%04x)\n", vendor_id, device_id);
+		return -1;
+	}
+
+	dev->pci_addr = i;
+	for (i = 0; i < PCI_BAR_NUM; i++) {
+		if (!pci_bar_is_valid(dev, i))
+			continue;
+		dev->pci_bar[i] = pci_bar_addr(dev, i);
+		printf("PCI: init dev 0x%04x BAR %d [%s] addr 0x%lx\n",
+		       dev->pci_addr, i, pci_bar_is_memory(dev, i) ?
+		       "MEM" : "IO", dev->pci_bar[i]);
+	}
+	dev->inited = true;
+
+	return 0;
+}
+
+static inline uint32_t pci_config_read_bar(pci_dev *dev, int n)
 {
-    unsigned dev;
-    for (dev = 0; dev < 256; ++dev) {
-    uint32_t id = pci_config_read(dev, 0);
-    if ((id & 0xFFFF) == vendor_id && (id >> 16) == device_id) {
-        return dev;
-    }
-    }
-    return PCIDEVADDR_INVALID;
+	return pci_config_read(dev->pci_addr,
+			       PCI_BASE_ADDRESS_0 + n * 4);
 }
 
-unsigned long pci_bar_addr(pcidevaddr_t dev, int bar_num)
+phys_addr_t pci_bar_addr(pci_dev *dev, int bar_num)
 {
-    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
-    if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
-        return bar & PCI_BASE_ADDRESS_IO_MASK;
-    } else {
-        return bar & PCI_BASE_ADDRESS_MEM_MASK;
-    }
+	uint32_t bar = pci_config_read_bar(dev, bar_num);
+	if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
+		return bar & PCI_BASE_ADDRESS_IO_MASK;
+	} else {
+		return bar & PCI_BASE_ADDRESS_MEM_MASK;
+	}
 }
 
-bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num)
+bool pci_bar_is_memory(pci_dev *dev, int bar_num)
 {
-    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
-    return !(bar & PCI_BASE_ADDRESS_SPACE_IO);
+	uint32_t bar = pci_config_read_bar(dev, bar_num);
+	return !(bar & PCI_BASE_ADDRESS_SPACE_IO);
 }
 
-bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num)
+bool pci_bar_is_valid(pci_dev *dev, int bar_num)
 {
-    uint32_t bar = pci_config_read(dev, PCI_BASE_ADDRESS_0 + bar_num * 4);
-    return bar;
+	return pci_config_read_bar(dev, bar_num);
 }
diff --git a/lib/pci.h b/lib/pci.h
index 9160cfb..b8755ff 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -14,10 +14,21 @@ typedef uint16_t pcidevaddr_t;
 enum {
     PCIDEVADDR_INVALID = 0xffff,
 };
-pcidevaddr_t pci_find_dev(uint16_t vendor_id, uint16_t device_id);
-unsigned long pci_bar_addr(pcidevaddr_t dev, int bar_num);
-bool pci_bar_is_memory(pcidevaddr_t dev, int bar_num);
-bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
+
+#define PCI_BAR_NUM                     (6)
+#define PCI_DEVFN_MAX                   (256)
+
+struct pci_dev {
+	bool inited;
+	uint16_t pci_addr;
+	phys_addr_t pci_bar[PCI_BAR_NUM];
+};
+typedef struct pci_dev pci_dev;
+
+int pci_dev_init(pci_dev *dev, uint16_t vendor_id, uint16_t device_id);
+phys_addr_t pci_bar_addr(pci_dev *dev, int bar_num);
+bool pci_bar_is_memory(pci_dev *dev, int bar_num);
+bool pci_bar_is_valid(pci_dev *dev, int bar_num);
 
 /*
  * pci-testdev is a driver for the pci-testdev qemu pci device. The
@@ -27,8 +38,6 @@ bool pci_bar_is_valid(pcidevaddr_t dev, int bar_num);
 #define PCI_VENDOR_ID_REDHAT		0x1b36
 #define PCI_DEVICE_ID_REDHAT_TEST	0x0005
 
-#define PCI_TESTDEV_NUM_BARS		2
-
 struct pci_test_dev_hdr {
 	uint8_t  test;
 	uint8_t  width;
@@ -39,4 +48,12 @@ struct pci_test_dev_hdr {
 	uint8_t  name[];
 };
 
+enum pci_dma_dir {
+	PCI_DMA_FROM_DEVICE = 0,
+	PCI_DMA_TO_DEVICE,
+};
+typedef enum pci_dma_dir pci_dma_dir_t;
+
+typedef uint64_t iova_t;
+
 #endif /* PCI_H */
diff --git a/x86/vmexit.c b/x86/vmexit.c
index c2e1e49..908d2dc 100644
--- a/x86/vmexit.c
+++ b/x86/vmexit.c
@@ -371,8 +371,7 @@ int main(int ac, char **av)
 {
 	struct fadt_descriptor_rev1 *fadt;
 	int i;
-	unsigned long membar = 0;
-	pcidevaddr_t pcidev;
+	pci_dev dev;
 
 	smp_init();
 	setup_vm();
@@ -385,21 +384,10 @@ int main(int ac, char **av)
 	pm_tmr_blk = fadt->pm_tmr_blk;
 	printf("PM timer port is %x\n", pm_tmr_blk);
 
-	pcidev = pci_find_dev(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_TEST);
-	if (pcidev != PCIDEVADDR_INVALID) {
-		for (i = 0; i < PCI_TESTDEV_NUM_BARS; i++) {
-			if (!pci_bar_is_valid(pcidev, i)) {
-				continue;
-			}
-			if (pci_bar_is_memory(pcidev, i)) {
-				membar = pci_bar_addr(pcidev, i);
-				pci_test.memaddr = ioremap(membar, PAGE_SIZE);
-			} else {
-				pci_test.iobar = pci_bar_addr(pcidev, i);
-			}
-		}
-		printf("pci-testdev at 0x%x membar %lx iobar %x\n",
-		       pcidev, membar, pci_test.iobar);
+	if (!pci_dev_init(&dev, PCI_VENDOR_ID_REDHAT,
+			  PCI_DEVICE_ID_REDHAT_TEST)) {
+		pci_test.memaddr = ioremap(dev.pci_bar[0], PAGE_SIZE);
+		pci_test.iobar = dev.pci_bar[1];
 	}
 
 	for (i = 0; i < ARRAY_SIZE(tests); ++i)
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux