[SeaBIOS] [PATCH v3 4/6] pci: init boot devices only on address space shortage

Michael S. Tsirkin mst at redhat.com
Tue Jul 5 18:23:47 CEST 2011


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 at 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



More information about the SeaBIOS mailing list