Since c2077e2c
"pci: Adjust PCI config limit based on bus topology",
pci_adjust_config_limit() has been used in the config space read and write
paths to only permit access to extended config space on buses which permit
it. Specifically it prevents access on devices below a vanilla-PCI bus via
some combination of bridges, even if both the host bridge and the device
itself are PCI-E.
It accomplishes this with a somewhat complex call up the chain of bridges
to see if any of them prohibit extended config space access. This is
overly complex, since we can always know if the bus will support such
access at the point it is constructed.
This patch simplifies the test by using a flag in the PCIBus instance
indicating whether extended configuration space is accessible. It is
false for vanilla PCI buses. For PCI-E buses, it is true for root
buses and equal to the parent bus's's capability otherwise.
For the special case of sPAPR's paravirtualized PCI root bus, which
acts mostly like vanilla PCI, but does allow extended config space
access, we override the default value of the flag from the host bridge
code.
This should cause no behavioural change.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <20190513061939.3464-4-david@gibson.dropbear.id.au>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
67 lines
1.7 KiB
C
67 lines
1.7 KiB
C
#ifndef QEMU_PCI_BUS_H
|
|
#define QEMU_PCI_BUS_H
|
|
|
|
#include "hw/pci/pci.h"
|
|
|
|
/*
|
|
* PCI Bus datastructures.
|
|
*
|
|
* Do not access the following members directly;
|
|
* use accessor functions in pci.h
|
|
*/
|
|
|
|
typedef struct PCIBusClass {
|
|
/*< private >*/
|
|
BusClass parent_class;
|
|
/*< public >*/
|
|
|
|
int (*bus_num)(PCIBus *bus);
|
|
uint16_t (*numa_node)(PCIBus *bus);
|
|
} PCIBusClass;
|
|
|
|
enum PCIBusFlags {
|
|
/* This bus is the root of a PCI domain */
|
|
PCI_BUS_IS_ROOT = 0x0001,
|
|
/* PCIe extended configuration space is accessible on this bus */
|
|
PCI_BUS_EXTENDED_CONFIG_SPACE = 0x0002,
|
|
};
|
|
|
|
struct PCIBus {
|
|
BusState qbus;
|
|
enum PCIBusFlags flags;
|
|
PCIIOMMUFunc iommu_fn;
|
|
void *iommu_opaque;
|
|
uint8_t devfn_min;
|
|
uint32_t slot_reserved_mask;
|
|
pci_set_irq_fn set_irq;
|
|
pci_map_irq_fn map_irq;
|
|
pci_route_irq_fn route_intx_to_irq;
|
|
void *irq_opaque;
|
|
PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX];
|
|
PCIDevice *parent_dev;
|
|
MemoryRegion *address_space_mem;
|
|
MemoryRegion *address_space_io;
|
|
|
|
QLIST_HEAD(, PCIBus) child; /* this will be replaced by qdev later */
|
|
QLIST_ENTRY(PCIBus) sibling;/* this will be replaced by qdev later */
|
|
|
|
/* The bus IRQ state is the logical OR of the connected devices.
|
|
Keep a count of the number of devices with raised IRQs. */
|
|
int nirq;
|
|
int *irq_count;
|
|
|
|
Notifier machine_done;
|
|
};
|
|
|
|
static inline bool pci_bus_is_root(PCIBus *bus)
|
|
{
|
|
return !!(bus->flags & PCI_BUS_IS_ROOT);
|
|
}
|
|
|
|
static inline bool pci_bus_allows_extended_config_space(PCIBus *bus)
|
|
{
|
|
return !!(bus->flags & PCI_BUS_EXTENDED_CONFIG_SPACE);
|
|
}
|
|
|
|
#endif /* QEMU_PCI_BUS_H */
|