On Tue, Jul 05, 2011 at 05:27:03PM +0200, Gerd Hoffmann wrote:
Try to handle address space shortage by skipping any device which isn't essential for boot.
Signed-off-by: Gerd Hoffmann kraxel@redhat.com
At least in a virt setup, it's much easier to debug things if boot just fails. Partial boot could be an option I guess. We usually have a list of bootable devices we got from qemu - want to use that?
src/pci.c | 3 +++ src/pciinit.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/util.h | 2 ++ 3 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/src/pci.c b/src/pci.c index 78bbac2..af735b2 100644 --- a/src/pci.c +++ b/src/pci.c @@ -193,6 +193,9 @@ pci_find_class(u16 classid) int pci_init_device(const struct pci_device_id *ids , struct pci_device *pci, void *arg) {
- if (!pci_enable_device(pci))
return -1;
- while (ids->vendid || ids->class_mask) { if ((ids->vendid == PCI_ANY_ID || ids->vendid == pci->vendor) && (ids->devid == PCI_ANY_ID || ids->devid == pci->device) &&
diff --git a/src/pciinit.c b/src/pciinit.c index aafdf7c..8b95132 100644 --- a/src/pciinit.c +++ b/src/pciinit.c @@ -44,6 +44,7 @@ static struct pci_bus { } r[PCI_REGION_TYPE_COUNT]; } *busses; static int busses_count; +static int boot_devices_only = 0;
static void pci_bios_init_device_in_bus(int bus); static void pci_bios_check_device_in_bus(int bus); @@ -157,6 +158,40 @@ static const struct pci_device_id pci_isa_bridge_tbl[] = { #define PCI_PREF_MEMORY_ALIGN (1UL << 20) #define PCI_PREF_MEMORY_SHIFT 16
+static int is_boot_device(struct pci_device *pci) +{
- /* check base class */
- switch (pci->class >> 8) {
- case PCI_BASE_CLASS_STORAGE:
- case PCI_BASE_CLASS_NETWORK:
- case PCI_BASE_CLASS_BRIDGE:
- case PCI_BASE_CLASS_SYSTEM:
return 1;
- }
- /* check class */
- switch (pci->class) {
- case PCI_CLASS_DISPLAY_VGA:
- case PCI_CLASS_SERIAL_USB:
return 1;
- }
- /* check if ROM present */
- if (pci->bars[PCI_ROM_SLOT].addr != 0) {
return 1;
- }
- return 0;
One worry here is that this list might not be exhaustive.
+}
+int pci_enable_device(struct pci_device *pci) +{
- if (boot_devices_only) {
return is_boot_device(pci);
- }
- return 1;
+}
static void storage_ide_init(struct pci_device *pci, void *arg) { u16 bdf = pci->bdf; @@ -385,6 +420,9 @@ static void pci_bios_check_device(struct pci_bus *bus, struct pci_device *dev) u32 limit; int i,type;
- if (!pci_enable_device(dev))
return;
- if (dev->class == PCI_CLASS_BRIDGE_PCI) { if (dev->secondary_bus >= busses_count) { /* should never trigger */
@@ -433,6 +471,9 @@ static void pci_bios_map_device(struct pci_bus *bus, struct pci_device *dev) u16 bdf = dev->bdf; int type, i;
- if (!pci_enable_device(dev))
return;
- if (dev->class == PCI_CLASS_BRIDGE_PCI) { if (dev->secondary_bus >= busses_count) { return;
@@ -595,8 +636,14 @@ pci_setup(void) busses = malloc_tmp(sizeof(*busses) * busses_count); pci_bios_check_device_in_bus(0 /* host bus */); if (pci_bios_init_root_regions(start, end) != 0) {
dprintf(1, "PCI: out of address space\n");
/* Hmm, what do now? */
dprintf(1, "=== PCI new allocation pass #1a (boot only) ===\n");
boot_devices_only = 1;
memset(busses, 0, busses_count * sizeof(struct pci_bus));
pci_bios_check_device_in_bus(0 /* host bus */);
if (pci_bios_init_root_regions(start, end) != 0) {
dprintf(1, "PCI: out of address space\n");
/* Hmm, what do now? */
}
}
dprintf(1, "=== PCI new allocation pass #2 ===\n");
diff --git a/src/util.h b/src/util.h index d856d50..8020181 100644 --- a/src/util.h +++ b/src/util.h @@ -347,6 +347,8 @@ void qemu_prep_reset(void); // pciinit.c extern const u8 pci_irqs[4]; void pci_setup(void); +struct pci_device; +int pci_enable_device(struct pci_device *pci);
// smm.c void smm_init(void); -- 1.7.1