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

Re: [RFCv4,17/35] plat/pci_bus: Split specific code into different files



Hi, Justin.

After applying all the patches in this series, I've tried to run httpreply and
everything worked fine with the arm64 build. However, when I've tried to build 
and
run the same app on x86_64, I've got this error:
`[    0.100170] ERR:  [libkvmpci] <pci_bus_x86.c @   88> PCI 00:02.00: Failed 
to initialize: Out of memory!`

Here is a description of the problem I've found. 
The pci_bus_handler (ph) used in the x86 specific code is declared in 
"pc_bus.h" as a static variable.
This header file is included in "pci_bus.c", where the functions that initialize
the fields of ph are defined, and also in "pci_bus_x86.c", where functions that
use ph during probing are defined.
Since ph is declared as static in "pci_bus.h",  all of it's fields are seen as 
empty
in "pci_bus_x86.c". When pci_driver_add_device() tries to use one of these 
fields
during probing, it fails and generates that OOM error.
The problem is not the memory, but the fact that uk_calloc() gets a null value 
as it's alloc function.

Since the only field of ph used in pci_bus_x86.c code was "ph.a"(uk_alloc), 
I've solved the issue
by sending it as a parameter to all of the functions that use it ("ph.a" was 
already
provided by "pci_probe()" to "arch_pci_probe()", the function that connects
"pci_bus.c" to architecture-specific sources).

Here is the diff between the original "pci_bus_x86.c" source in the patch and
the fixed one.

--- pci_bus_x86_original.c      2021-03-14 20:34:34.610336281 +0200
+++ pci_bus_x86.c       2021-03-14 20:36:45.523341015 +0200
@@ -68,7 +68,8 @@
 
 static inline int pci_driver_add_device(struct pci_driver *drv,
                                        struct pci_address *addr,
-                                       struct pci_device_id *devid)
+                                       struct pci_device_id *devid,
+                                       struct uk_alloc *pha)
 {
        struct pci_device *dev;
        uint32_t config_addr;
@@ -79,7 +80,7 @@
        UK_ASSERT(addr != NULL);
        UK_ASSERT(devid != NULL);
 
-       dev = (struct pci_device *) uk_calloc(ph.a, 1, sizeof(*dev));
+       dev = (struct pci_device *) uk_calloc(pha, 1, sizeof(*dev));
        if (!dev) {
                uk_pr_err("PCI %02x:%02x.%02x: Failed to initialize: Out of 
memory!\n",
                          (int) addr->bus,
@@ -109,12 +110,12 @@
        return 0;
 }
 
-static void probe_bus(uint32_t);
+static void probe_bus(uint32_t, struct uk_alloc *pha);
 
 /* Probe a function. Return 1 if the function does not exist in the device, 0
  * otherwise.
  */
-static int probe_function(uint32_t bus, uint32_t device, uint32_t function)
+static int probe_function(uint32_t bus, uint32_t device, uint32_t function, 
struct uk_alloc *pha)
 {
        uint32_t config_addr, config_data, subclass, secondary_bus;
        struct pci_address addr;
@@ -169,14 +170,14 @@
                uk_pr_info("<no driver>\n");
        } else {
                uk_pr_info("driver %p\n", drv);
-               pci_driver_add_device(drv, &addr, &devid);
+               pci_driver_add_device(drv, &addr, &devid, pha);
        }
 
        /* 0x06 = Bridge Device, 0x04 = PCI-to-PCI bridge */
        if ((devid.class_id == 0x06) && (subclass == 0x04) ) {
                PCI_CONF_READ(uint32_t, &secondary_bus,
                                config_addr, SECONDARY_BUS);
-               probe_bus(secondary_bus);
+               probe_bus(secondary_bus, pha);
        }
 
        return 0;
@@ -185,12 +186,12 @@
 /* Recursive PCI enumeration: this function is called recursively by
  * probe_function upon discovering PCI-to-PCI bridges.
  */
-static void probe_bus(uint32_t bus)
+static void probe_bus(uint32_t bus, struct uk_alloc *pha)
 {
        uint32_t config_addr, device, header_type, function = 0;
 
        for (device = 0; device < PCI_MAX_DEVICES; ++device) {
-               if (!probe_function(bus, device, function))
+               if (!probe_function(bus, device, function, pha))
                        continue;
 
                config_addr = (PCI_ENABLE_BIT);
@@ -203,11 +204,11 @@
 
                /* Check remaining functions */
                for (function = 1; function < PCI_MAX_FUNCTIONS; function++)
-                       probe_function(bus, device, function);
+                       probe_function(bus, device, function, pha);
        }
 }
 
-int arch_pci_probe(void)
+int arch_pci_probe(struct uk_alloc *pha)
 {
        uint32_t config_addr, function, header_type, vendor_id;
 
@@ -219,7 +220,7 @@
 
        if ((header_type & PCI_HEADER_TYPE_MSB_MASK) == 0) {
                /* Single PCI host controller */
-               probe_bus(0);
+               probe_bus(0, pha);
        } else {
                /* Multiple PCI host controllers */
                for (function = 0; function < PCI_MAX_FUNCTIONS; function++) {
@@ -232,7 +233,7 @@
                        if (vendor_id != PCI_INVALID_ID)
                                break;
 
-                       probe_bus(function);
+                       probe_bus(function, pha);
                }
        }

Reviewed-by: Razvan Virtan <virtanrazvan@xxxxxxxxx>



 


Rackspace

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