pc, pci, virtio: features, fixes, cleanups

A bunch of fixes, cleanus and new features all over the place.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJaV8NpAAoJECgfDbjSjVRpve8IAMuT4Na9gn0SGZnzarF5Bn4H
 D7oIOHCVkJPFZXD4Eqv39JFJJbDKPszSSHuoYt8zqXd4N6ZOBiV39cVhUCV1f/7H
 /gzfTGr+s1NzxKKhdjh4jNM0RgUQR5j11Dz3G4wbTtx2LA2kYm/zWsnqNJwYo4tX
 SbwmU7RHa/5O3aJQ1LQgWJ7uPwuIuc84gWciKKRiYa3f7WNu+5j1dLhKtop5Boww
 AlK63tLfLyQczo1k+PUak1j5kD2v6dNZX1wRS6QZkA1Bj0GnHlE5bBycu8l4B88F
 mBYCLVBY4bOhweKSzxM2a90Q3uz+HffMl04M4drPnaEqltbsYDrSwiC8RJqMIjo=
 =Jkdo
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pc, pci, virtio: features, fixes, cleanups

A bunch of fixes, cleanus and new features all over the place.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Thu 11 Jan 2018 20:04:57 GMT
# gpg:                using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream: (23 commits)
  smbus: do not immediately complete commands
  dump-guest-memory.py: fix "You can't do that without a process to debug"
  virtio-pci: Don't force Subsystem Vendor ID = Vendor ID
  intel_iommu: fix error param in string
  intel_iommu: remove X86_IOMMU_PCI_DEVFN_MAX
  vhost-user: document memory accesses
  vhost-user: fix indentation in protocol specification
  hw/pci-host/xilinx: QOM'ify the AXI-PCIe host bridge
  hw/pci-host/piix: QOM'ify the IGD Passthrough host bridge
  tests/pxe-test: Add some extra tests
  tests/pxe-test: Test net booting over IPv6 in some cases
  tests/pxe-test: Use table of testcases rather than open-coding
  tests/pxe-test: Remove unnecessary special case test functions
  virtio_error: don't invoke status callbacks
  pci: Eliminate pci_find_primary_bus()
  pci: Eliminate redundant PCIDevice::bus pointer
  pci: Add pci_dev_bus_num() helper
  pci: Move bridge data structures from pci_bus.h to pci_bridge.h
  pci: Rename root bus initialization functions for clarity
  tests: add test to check VirtQueue object
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2018-01-12 09:52:58 +00:00
commit 36b5e43af8
53 changed files with 643 additions and 387 deletions

View File

@ -53,8 +53,8 @@ Depending on the request type, payload can be:
* A vring state description
---------------
| index | num |
---------------
| index | num |
---------------
Index: a 32-bit index
Num: a 32-bit number
@ -66,11 +66,14 @@ Depending on the request type, payload can be:
Index: a 32-bit vring index
Flags: a 32-bit vring flags
Descriptor: a 64-bit user address of the vring descriptor table
Used: a 64-bit user address of the vring used ring
Available: a 64-bit user address of the vring available ring
Descriptor: a 64-bit ring address of the vring descriptor table
Used: a 64-bit ring address of the vring used ring
Available: a 64-bit ring address of the vring available ring
Log: a 64-bit guest address for logging
Note that a ring address is an IOVA if VIRTIO_F_IOMMU_PLATFORM has been
negotiated. Otherwise it is a user address.
* Memory regions description
---------------------------------------------------
| num regions | padding | region0 | ... | region7 |
@ -273,6 +276,30 @@ Once the source has finished migration, rings will be stopped by
the source. No further update must be done before rings are
restarted.
Memory access
-------------
The master sends a list of vhost memory regions to the slave using the
VHOST_USER_SET_MEM_TABLE message. Each region has two base addresses: a guest
address and a user address.
Messages contain guest addresses and/or user addresses to reference locations
within the shared memory. The mapping of these addresses works as follows.
User addresses map to the vhost memory region containing that user address.
When the VIRTIO_F_IOMMU_PLATFORM feature has not been negotiated:
* Guest addresses map to the vhost memory region containing that guest
address.
When the VIRTIO_F_IOMMU_PLATFORM feature has been negotiated:
* Guest addresses are also called I/O virtual addresses (IOVAs). They are
translated to user addresses via the IOTLB.
* The vhost memory region guest address is not used.
IOMMU support
-------------

View File

@ -223,7 +223,7 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
{
PCIDevice *pdev = PCI_DEVICE(dev);
int slot = PCI_SLOT(pdev->devfn);
int bsel = acpi_pcihp_get_bsel(pdev->bus);
int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
if (bsel < 0) {
error_setg(errp, "Unsupported bus. Bus doesn't have property '"
ACPI_PCIHP_PROP_BSEL "' set");
@ -246,7 +246,7 @@ void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
{
PCIDevice *pdev = PCI_DEVICE(dev);
int slot = PCI_SLOT(pdev->devfn);
int bsel = acpi_pcihp_get_bsel(pdev->bus);
int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
if (bsel < 0) {
error_setg(errp, "Unsupported bus. Bus doesn't have property '"
ACPI_PCIHP_PROP_BSEL "' set");

View File

@ -460,9 +460,9 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
(memory_region_present(io_as, 0x2f8) ? 0x90 : 0);
if (s->use_acpi_pci_hotplug) {
pci_for_each_bus(d->bus, piix4_update_bus_hotplug, s);
pci_for_each_bus(pci_get_bus(d), piix4_update_bus_hotplug, s);
} else {
piix4_update_bus_hotplug(d->bus, s);
piix4_update_bus_hotplug(pci_get_bus(d), s);
}
}
@ -535,7 +535,8 @@ static void piix4_pm_realize(PCIDevice *dev, Error **errp)
qemu_add_machine_init_done_notifier(&s->machine_ready);
qemu_register_reset(piix4_reset, s);
piix4_acpi_system_hot_add_init(pci_address_space_io(dev), dev->bus, s);
piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
pci_get_bus(dev), s);
piix4_pm_add_propeties(s);
}

View File

@ -162,21 +162,6 @@ static void vmgenid_update_guest(VmGenIdState *vms)
}
}
static void vmgenid_set_guid(Object *obj, const char *value, Error **errp)
{
VmGenIdState *vms = VMGENID(obj);
if (!strcmp(value, "auto")) {
qemu_uuid_generate(&vms->guid);
} else if (qemu_uuid_parse(value, &vms->guid) < 0) {
error_setg(errp, "'%s. %s': Failed to parse GUID string: %s",
object_get_typename(OBJECT(vms)), VMGENID_GUID, value);
return;
}
vmgenid_update_guest(vms);
}
/* After restoring an image, we need to update the guest memory and notify
* it of a potential change to VM Generation ID
*/
@ -224,23 +209,24 @@ static void vmgenid_realize(DeviceState *dev, Error **errp)
}
qemu_register_reset(vmgenid_handle_reset, vms);
vmgenid_update_guest(vms);
}
static Property vmgenid_device_properties[] = {
DEFINE_PROP_UUID(VMGENID_GUID, VmGenIdState, guid),
DEFINE_PROP_END_OF_LIST(),
};
static void vmgenid_device_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &vmstate_vmgenid;
dc->realize = vmgenid_realize;
dc->props = vmgenid_device_properties;
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
object_class_property_add_str(klass, VMGENID_GUID, NULL,
vmgenid_set_guid, NULL);
object_class_property_set_description(klass, VMGENID_GUID,
"Set Global Unique Identifier "
"(big-endian) or auto for random value",
NULL);
}
static const TypeInfo vmgenid_device_info = {

View File

@ -881,10 +881,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
memory_region_add_subregion(addr_space, 0x801fc000000ULL,
&s->pchip.reg_io);
b = pci_register_bus(dev, "pci",
typhoon_set_irq, sys_map_irq, s,
&s->pchip.reg_mem, &s->pchip.reg_io,
0, 64, TYPE_PCI_BUS);
b = pci_register_root_bus(dev, "pci",
typhoon_set_irq, sys_map_irq, s,
&s->pchip.reg_mem, &s->pchip.reg_io,
0, 64, TYPE_PCI_BUS);
phb->bus = b;
qdev_init_nofail(dev);

View File

@ -10,6 +10,7 @@
#include "net/hub.h"
#include "qapi/visitor.h"
#include "chardev/char.h"
#include "qemu/uuid.h"
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
Error **errp)
@ -883,6 +884,66 @@ const PropertyInfo qdev_prop_pci_host_devaddr = {
.set = set_pci_host_devaddr,
};
/* --- UUID --- */
static void get_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
char buffer[UUID_FMT_LEN + 1];
char *p = buffer;
qemu_uuid_unparse(uuid, buffer);
visit_type_str(v, name, &p, errp);
}
#define UUID_VALUE_AUTO "auto"
static void set_uuid(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
QemuUUID *uuid = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
char *str;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
visit_type_str(v, name, &str, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (!strcmp(str, UUID_VALUE_AUTO)) {
qemu_uuid_generate(uuid);
} else if (qemu_uuid_parse(str, uuid) < 0) {
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
}
g_free(str);
}
static void set_default_uuid_auto(Object *obj, const Property *prop)
{
object_property_set_str(obj, UUID_VALUE_AUTO, prop->name, &error_abort);
}
const PropertyInfo qdev_prop_uuid = {
.name = "str",
.description = "UUID (aka GUID) or \"" UUID_VALUE_AUTO
"\" for random value (default)",
.get = get_uuid,
.set = set_uuid,
.set_default_value = set_default_uuid_auto,
};
/* --- support for array properties --- */
/* Used as an opaque for the object properties we add for each

View File

@ -62,6 +62,9 @@ static void smb_transaction(PMSMBus *s)
I2CBus *bus = s->smbus;
int ret;
assert(s->smb_stat & STS_HOST_BUSY);
s->smb_stat &= ~STS_HOST_BUSY;
SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
/* Transaction isn't exec if STS_DEV_ERR bit set */
if ((s->smb_stat & STS_DEV_ERR) != 0) {
@ -134,6 +137,13 @@ error:
}
static void smb_transaction_start(PMSMBus *s)
{
/* Do not execute immediately the command ; it will be
* executed when guest will read SMB_STAT register */
s->smb_stat |= STS_HOST_BUSY;
}
static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
unsigned width)
{
@ -149,7 +159,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
case SMBHSTCNT:
s->smb_ctl = val;
if (val & 0x40)
smb_transaction(s);
smb_transaction_start(s);
break;
case SMBHSTCMD:
s->smb_cmd = val;
@ -181,6 +191,10 @@ static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
switch(addr) {
case SMBHSTSTS:
val = s->smb_stat;
if (s->smb_stat & STS_HOST_BUSY) {
/* execute command now */
smb_transaction(s);
}
break;
case SMBHSTCNT:
s->smb_index = 0;

View File

@ -186,7 +186,7 @@ static void vtd_reset_context_cache(IntelIOMMUState *s)
g_hash_table_iter_init(&bus_it, s->vtd_as_by_busptr);
while (g_hash_table_iter_next (&bus_it, NULL, (void**)&vtd_bus)) {
for (devfn_it = 0; devfn_it < X86_IOMMU_PCI_DEVFN_MAX; ++devfn_it) {
for (devfn_it = 0; devfn_it < PCI_DEVFN_MAX; ++devfn_it) {
vtd_as = vtd_bus->dev_as[devfn_it];
if (!vtd_as) {
continue;
@ -1002,7 +1002,7 @@ static void vtd_switch_address_space_all(IntelIOMMUState *s)
g_hash_table_iter_init(&iter, s->vtd_as_by_busptr);
while (g_hash_table_iter_next(&iter, NULL, (void **)&vtd_bus)) {
for (i = 0; i < X86_IOMMU_PCI_DEVFN_MAX; i++) {
for (i = 0; i < PCI_DEVFN_MAX; i++) {
if (!vtd_bus->dev_as[i]) {
continue;
}
@ -1294,7 +1294,7 @@ static void vtd_context_device_invalidate(IntelIOMMUState *s,
vtd_bus = vtd_find_as_from_bus_num(s, bus_n);
if (vtd_bus) {
devfn = VTD_SID_TO_DEVFN(source_id);
for (devfn_it = 0; devfn_it < X86_IOMMU_PCI_DEVFN_MAX; ++devfn_it) {
for (devfn_it = 0; devfn_it < PCI_DEVFN_MAX; ++devfn_it) {
vtd_as = vtd_bus->dev_as[devfn_it];
if (vtd_as && ((devfn_it & mask) == (devfn & mask))) {
trace_vtd_inv_desc_cc_device(bus_n, VTD_PCI_SLOT(devfn_it),
@ -2327,7 +2327,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
IntelIOMMUNotifierNode *next_node = NULL;
if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) {
error_report("We need to set cache_mode=1 for intel-iommu to enable "
error_report("We need to set caching-mode=1 for intel-iommu to enable "
"device assignment with IOMMU protection.");
exit(1);
}
@ -2699,7 +2699,7 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
*new_key = (uintptr_t)bus;
/* No corresponding free() */
vtd_bus = g_malloc0(sizeof(VTDBus) + sizeof(VTDAddressSpace *) * \
X86_IOMMU_PCI_DEVFN_MAX);
PCI_DEVFN_MAX);
vtd_bus->bus = bus;
g_hash_table_insert(s->vtd_as_by_busptr, new_key, vtd_bus);
}
@ -2982,7 +2982,7 @@ static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
IntelIOMMUState *s = opaque;
VTDAddressSpace *vtd_as;
assert(0 <= devfn && devfn < X86_IOMMU_PCI_DEVFN_MAX);
assert(0 <= devfn && devfn < PCI_DEVFN_MAX);
vtd_as = vtd_find_add_as(s, bus, devfn);
return &vtd_as->as;

View File

@ -394,7 +394,7 @@ static void pc_xen_hvm_init_pci(MachineState *machine)
static void pc_xen_hvm_init(MachineState *machine)
{
PCIBus *bus;
PCMachineState *pcms = PC_MACHINE(machine);
if (!xen_enabled()) {
error_report("xenfv machine requires the xen accelerator");
@ -402,11 +402,7 @@ static void pc_xen_hvm_init(MachineState *machine)
}
pc_xen_hvm_init_pci(machine);
bus = pci_find_primary_bus();
if (bus != NULL) {
pci_create_simple(bus, -1, "xen-platform");
}
pci_create_simple(pcms->bus, -1, "xen-platform");
}
#endif

View File

@ -185,11 +185,11 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
if (val & (UNPLUG_IDE_SCSI_DISKS | UNPLUG_AUX_IDE_DISKS |
UNPLUG_NVME_DISKS)) {
DPRINTF("unplug disks\n");
pci_unplug_disks(pci_dev->bus, val);
pci_unplug_disks(pci_get_bus(pci_dev), val);
}
if (val & UNPLUG_ALL_NICS) {
DPRINTF("unplug nics\n");
pci_unplug_nics(pci_dev->bus);
pci_unplug_nics(pci_get_bus(pci_dev));
}
break;
}
@ -371,17 +371,17 @@ static void xen_platform_ioport_writeb(void *opaque, hwaddr addr,
* If VMDP was to control both disk and LAN it would use 4.
* If it controlled just disk or just LAN, it would use 8 below.
*/
pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS);
pci_unplug_nics(pci_dev->bus);
pci_unplug_disks(pci_get_bus(pci_dev), UNPLUG_IDE_SCSI_DISKS);
pci_unplug_nics(pci_get_bus(pci_dev));
}
break;
case 8:
switch (val) {
case 1:
pci_unplug_disks(pci_dev->bus, UNPLUG_IDE_SCSI_DISKS);
pci_unplug_disks(pci_get_bus(pci_dev), UNPLUG_IDE_SCSI_DISKS);
break;
case 2:
pci_unplug_nics(pci_dev->bus);
pci_unplug_nics(pci_get_bus(pci_dev));
break;
default:
log_writeb(s, (uint32_t)val);

View File

@ -162,7 +162,7 @@ static void ich9_cc_write(void *opaque, hwaddr addr,
ich9_cc_addr_len(&addr, &len);
memcpy(lpc->chip_config + addr, &val, len);
pci_bus_fire_intx_routing_notifier(lpc->d.bus);
pci_bus_fire_intx_routing_notifier(pci_get_bus(&lpc->d));
ich9_cc_update(lpc);
}
@ -218,7 +218,7 @@ static void ich9_lpc_update_pic(ICH9LPCState *lpc, int gsi)
int tmp_dis;
ich9_lpc_pic_irq(lpc, i, &tmp_irq, &tmp_dis);
if (!tmp_dis && tmp_irq == gsi) {
pic_level |= pci_bus_get_irq_level(lpc->d.bus, i);
pic_level |= pci_bus_get_irq_level(pci_get_bus(&lpc->d), i);
}
}
if (gsi == lpc->sci_gsi) {
@ -246,7 +246,7 @@ static void ich9_lpc_update_apic(ICH9LPCState *lpc, int gsi)
assert(gsi >= ICH9_LPC_PIC_NUM_PINS);
level |= pci_bus_get_irq_level(lpc->d.bus, ich9_gsi_to_pirq(gsi));
level |= pci_bus_get_irq_level(pci_get_bus(&lpc->d), ich9_gsi_to_pirq(gsi));
if (gsi == lpc->sci_gsi) {
level |= lpc->sci_level;
}
@ -524,10 +524,10 @@ static void ich9_lpc_config_write(PCIDevice *d,
ich9_lpc_rcba_update(lpc, rcba_old);
}
if (ranges_overlap(addr, len, ICH9_LPC_PIRQA_ROUT, 4)) {
pci_bus_fire_intx_routing_notifier(lpc->d.bus);
pci_bus_fire_intx_routing_notifier(pci_get_bus(&lpc->d));
}
if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
pci_bus_fire_intx_routing_notifier(lpc->d.bus);
pci_bus_fire_intx_routing_notifier(pci_get_bus(&lpc->d));
}
if (ranges_overlap(addr, len, ICH9_LPC_GEN_PMCON_1, 8)) {
ich9_lpc_pmcon_update(lpc);

View File

@ -1171,12 +1171,12 @@ PCIBus *gt64120_register(qemu_irq *pic)
phb = PCI_HOST_BRIDGE(dev);
memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", UINT32_MAX);
address_space_init(&d->pci0_mem_as, &d->pci0_mem, "pci0-mem");
phb->bus = pci_register_bus(dev, "pci",
gt64120_pci_set_irq, gt64120_pci_map_irq,
pic,
&d->pci0_mem,
get_system_io(),
PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
phb->bus = pci_register_root_bus(dev, "pci",
gt64120_pci_set_irq, gt64120_pci_map_irq,
pic,
&d->pci0_mem,
get_system_io(),
PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
qdev_init_nofail(dev);
memory_region_init_io(&d->ISD_mem, OBJECT(dev), &isd_mem_ops, d, "isd-mem", 0x1000);

View File

@ -2356,7 +2356,7 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
vmxnet3_net_init(s);
if (pci_is_express(pci_dev)) {
if (pci_bus_is_express(pci_dev->bus)) {
if (pci_bus_is_express(pci_get_bus(pci_dev))) {
pcie_endpoint_cap_init(pci_dev, VMXNET3_EXP_EP_OFFSET);
}

View File

@ -51,7 +51,8 @@ typedef struct PXBDev {
static PXBDev *convert_to_pxb(PCIDevice *dev)
{
return pci_bus_is_express(dev->bus) ? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
return pci_bus_is_express(pci_get_bus(dev))
? PXB_PCIE_DEV(dev) : PXB_DEV(dev);
}
static GList *pxb_dev_list;
@ -165,7 +166,7 @@ static const TypeInfo pxb_host_info = {
*/
static void pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus, Error **errp)
{
PCIBus *bus = dev->bus;
PCIBus *bus = pci_get_bus(dev);
int pxb_bus_num = pci_bus_num(pxb_bus);
if (bus->parent_dev) {
@ -179,12 +180,12 @@ static void pxb_register_bus(PCIDevice *dev, PCIBus *pxb_bus, Error **errp)
return;
}
}
QLIST_INSERT_HEAD(&dev->bus->child, pxb_bus, sibling);
QLIST_INSERT_HEAD(&pci_get_bus(dev)->child, pxb_bus, sibling);
}
static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
{
PCIDevice *pxb = pci_dev->bus->parent_dev;
PCIDevice *pxb = pci_get_bus(pci_dev)->parent_dev;
/*
* The bios does not index the pxb slot number when
@ -229,9 +230,9 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
ds = qdev_create(NULL, TYPE_PXB_HOST);
if (pcie) {
bus = pci_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
bus = pci_root_bus_new(ds, dev_name, NULL, NULL, 0, TYPE_PXB_PCIE_BUS);
} else {
bus = pci_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
bus = pci_root_bus_new(ds, "pxb-internal", NULL, NULL, 0, TYPE_PXB_BUS);
bds = qdev_create(BUS(bus), "pci-bridge");
bds->id = dev_name;
qdev_prop_set_uint8(bds, PCI_BRIDGE_DEV_PROP_CHASSIS_NR, pxb->bus_nr);
@ -239,8 +240,8 @@ static void pxb_dev_realize_common(PCIDevice *dev, bool pcie, Error **errp)
}
bus->parent_dev = dev;
bus->address_space_mem = dev->bus->address_space_mem;
bus->address_space_io = dev->bus->address_space_io;
bus->address_space_mem = pci_get_bus(dev)->address_space_mem;
bus->address_space_io = pci_get_bus(dev)->address_space_io;
bus->map_irq = pxb_map_irq_fn;
PCI_HOST_BRIDGE(ds)->bus = bus;
@ -271,7 +272,7 @@ err_register_bus:
static void pxb_dev_realize(PCIDevice *dev, Error **errp)
{
if (pci_bus_is_express(dev->bus)) {
if (pci_bus_is_express(pci_get_bus(dev))) {
error_setg(errp, "pxb devices cannot reside on a PCIe bus");
return;
}
@ -323,7 +324,7 @@ static const TypeInfo pxb_dev_info = {
static void pxb_pcie_dev_realize(PCIDevice *dev, Error **errp)
{
if (!pci_bus_is_express(dev->bus)) {
if (!pci_bus_is_express(pci_get_bus(dev))) {
error_setg(errp, "pxb-pcie devices cannot reside on a PCI bus");
return;
}

View File

@ -433,11 +433,11 @@ static void pci_pbm_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(get_system_memory(), s->mem_base,
&s->pci_mmio);
phb->bus = pci_register_bus(dev, "pci",
pci_apb_set_irq, pci_apb_map_irq, s,
&s->pci_mmio,
&s->pci_ioport,
0, 32, TYPE_PCI_BUS);
phb->bus = pci_register_root_bus(dev, "pci",
pci_apb_set_irq, pci_apb_map_irq, s,
&s->pci_mmio,
&s->pci_ioport,
0, 32, TYPE_PCI_BUS);
pci_create_simple(phb->bus, 0, "pbm-pci");

View File

@ -714,10 +714,10 @@ static int bonito_pcihost_initfn(SysBusDevice *dev)
{
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
phb->bus = pci_register_bus(DEVICE(dev), "pci",
pci_bonito_set_irq, pci_bonito_map_irq, dev,
get_system_memory(), get_system_io(),
0x28, 32, TYPE_PCI_BUS);
phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
pci_bonito_set_irq, pci_bonito_map_irq,
dev, get_system_memory(), get_system_io(),
0x28, 32, TYPE_PCI_BUS);
return 0;
}

View File

@ -89,9 +89,9 @@ static void gpex_host_realize(DeviceState *dev, Error **errp)
s->irq_num[i] = -1;
}
pci->bus = pci_register_bus(dev, "pcie.0", gpex_set_irq,
pci_swizzle_map_irq_fn, s, &s->io_mmio,
&s->io_ioport, 0, 4, TYPE_PCIE_BUS);
pci->bus = pci_register_root_bus(dev, "pcie.0", gpex_set_irq,
pci_swizzle_map_irq_fn, s, &s->io_mmio,
&s->io_ioport, 0, 4, TYPE_PCIE_BUS);
qdev_set_parent_bus(DEVICE(&s->gpex_root), BUS(pci->bus));
pci_bus_set_route_irq_fn(pci->bus, gpex_route_intx_pin_to_irq);

View File

@ -82,13 +82,13 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
phb->bus = pci_register_bus(dev, NULL,
pci_grackle_set_irq,
pci_grackle_map_irq,
pic,
&d->pci_mmio,
address_space_io,
0, 4, TYPE_PCI_BUS);
phb->bus = pci_register_root_bus(dev, NULL,
pci_grackle_set_irq,
pci_grackle_map_irq,
pic,
&d->pci_mmio,
address_space_io,
0, 4, TYPE_PCI_BUS);
pci_create_simple(phb->bus, 0, "grackle");
qdev_init_nofail(dev);

View File

@ -361,8 +361,8 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,
dev = qdev_create(NULL, host_type);
s = PCI_HOST_BRIDGE(dev);
b = pci_bus_new(dev, NULL, pci_address_space,
address_space_io, 0, TYPE_PCI_BUS);
b = pci_root_bus_new(dev, NULL, pci_address_space,
address_space_io, 0, TYPE_PCI_BUS);
s->bus = b;
object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
qdev_init_nofail(dev);
@ -512,12 +512,12 @@ static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pin)
/* irq routing is changed. so rebuild bitmap */
static void piix3_update_irq_levels(PIIX3State *piix3)
{
PCIBus *bus = pci_get_bus(&piix3->dev);
int pirq;
piix3->pic_levels = 0;
for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
piix3_set_irq_level(piix3, pirq,
pci_bus_get_irq_level(piix3->dev.bus, pirq));
piix3_set_irq_level(piix3, pirq, pci_bus_get_irq_level(bus, pirq));
}
}
@ -529,7 +529,7 @@ static void piix3_write_config(PCIDevice *dev,
PIIX3State *piix3 = PIIX3_PCI_DEVICE(dev);
int pic_irq;
pci_bus_fire_intx_routing_notifier(piix3->dev.bus);
pci_bus_fire_intx_routing_notifier(pci_get_bus(&piix3->dev));
piix3_update_irq_levels(piix3);
for (pic_irq = 0; pic_irq < PIIX_NUM_PIC_IRQS; pic_irq++) {
piix3_set_irq_pic(piix3, pic_irq);
@ -601,7 +601,7 @@ static int piix3_post_load(void *opaque, int version_id)
piix3->pic_levels = 0;
for (pirq = 0; pirq < PIIX_NUM_PIRQS; pirq++) {
piix3_set_irq_level_internal(piix3, pirq,
pci_bus_get_irq_level(piix3->dev.bus, pirq));
pci_bus_get_irq_level(pci_get_bus(&piix3->dev), pirq));
}
return 0;
}
@ -613,7 +613,7 @@ static int piix3_pre_save(void *opaque)
for (i = 0; i < ARRAY_SIZE(piix3->pci_irq_levels_vmstate); i++) {
piix3->pci_irq_levels_vmstate[i] =
pci_bus_get_irq_level(piix3->dev.bus, i);
pci_bus_get_irq_level(pci_get_bus(&piix3->dev), i);
}
return 0;
@ -804,60 +804,55 @@ static const IGDHostInfo igd_host_bridge_infos[] = {
{0xa8, 4}, /* SNB: base of GTT stolen memory */
};
static int host_pci_config_read(int pos, int len, uint32_t *val)
static void host_pci_config_read(int pos, int len, uint32_t *val, Error **errp)
{
char path[PATH_MAX];
int config_fd;
ssize_t size = sizeof(path);
int rc, config_fd;
/* Access real host bridge. */
int rc = snprintf(path, size, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
0, 0, 0, 0, "config");
int ret = 0;
if (rc >= size || rc < 0) {
return -ENODEV;
}
char *path = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%d/%s",
0, 0, 0, 0, "config");
config_fd = open(path, O_RDWR);
if (config_fd < 0) {
return -ENODEV;
error_setg_errno(errp, errno, "Failed to open: %s", path);
goto out;
}
if (lseek(config_fd, pos, SEEK_SET) != pos) {
ret = -errno;
goto out;
error_setg_errno(errp, errno, "Failed to seek: %s", path);
goto out_close_fd;
}
do {
rc = read(config_fd, (uint8_t *)val, len);
} while (rc < 0 && (errno == EINTR || errno == EAGAIN));
if (rc != len) {
ret = -errno;
error_setg_errno(errp, errno, "Failed to read: %s", path);
}
out:
out_close_fd:
close(config_fd);
return ret;
out:
g_free(path);
}
static int igd_pt_i440fx_initfn(struct PCIDevice *pci_dev)
static void igd_pt_i440fx_realize(PCIDevice *pci_dev, Error **errp)
{
uint32_t val = 0;
int rc, i, num;
int i, num;
int pos, len;
Error *local_err = NULL;
num = ARRAY_SIZE(igd_host_bridge_infos);
for (i = 0; i < num; i++) {
pos = igd_host_bridge_infos[i].offset;
len = igd_host_bridge_infos[i].len;
rc = host_pci_config_read(pos, len, &val);
if (rc) {
return -ENODEV;
host_pci_config_read(pos, len, &val, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
pci_default_write_config(pci_dev, pos, val, len);
}
return 0;
}
static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data)
@ -865,7 +860,7 @@ static void igd_passthrough_i440fx_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->init = igd_pt_i440fx_initfn;
k->realize = igd_pt_i440fx_realize;
dc->desc = "IGD Passthrough Host bridge";
}

View File

@ -460,9 +460,9 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
/* PIO lives at the bottom of our bus space */
memory_region_add_subregion_overlap(&s->busmem, 0, &s->pio, -2);
b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
b = pci_register_root_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
mpc85xx_pci_map_irq, s, &s->busmem, &s->pio,
PCI_DEVFN(s->first_slot, 0), 4, TYPE_PCI_BUS);
h->bus = b;
/* Set up PCI view of memory */

View File

@ -269,8 +269,8 @@ static void raven_pcihost_initfn(Object *obj)
memory_region_add_subregion_overlap(address_space_mem, 0x80000000,
&s->pci_io_non_contiguous, 1);
memory_region_add_subregion(address_space_mem, 0xc0000000, &s->pci_memory);
pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
&s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), DEVICE(obj), NULL,
&s->pci_memory, &s->pci_io, 0, TYPE_PCI_BUS);
/* Bus master address space */
memory_region_init(&s->bm, obj, "bm-raven", UINT32_MAX);

View File

@ -51,9 +51,10 @@ static void q35_host_realize(DeviceState *dev, Error **errp)
sysbus_add_io(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem);
sysbus_init_ioports(sbd, MCH_HOST_BRIDGE_CONFIG_DATA, 4);
pci->bus = pci_bus_new(DEVICE(s), "pcie.0",
s->mch.pci_address_space, s->mch.address_space_io,
0, TYPE_PCIE_BUS);
pci->bus = pci_root_bus_new(DEVICE(s), "pcie.0",
s->mch.pci_address_space,
s->mch.address_space_io,
0, TYPE_PCIE_BUS);
PC_MACHINE(qdev_get_machine())->bus = pci->bus;
qdev_set_parent_bus(DEVICE(&s->mch), BUS(pci->bus));
qdev_init_nofail(DEVICE(&s->mch));

View File

@ -233,12 +233,12 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
h->bus = pci_register_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
address_space_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
address_space_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
#if 0
pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north");
@ -299,12 +299,12 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic,
memory_region_add_subregion(address_space_mem, 0x80000000ULL,
&d->pci_hole);
h->bus = pci_register_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
address_space_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
h->bus = pci_register_root_bus(dev, NULL,
pci_unin_set_irq, pci_unin_map_irq,
pic,
&d->pci_mmio,
address_space_io,
PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS);
sysbus_mmio_map(s, 0, 0xf0800000);
sysbus_mmio_map(s, 1, 0xf0c00000);

View File

@ -311,7 +311,7 @@ static const MemoryRegionOps pci_vpb_config_ops = {
static int pci_vpb_map_irq(PCIDevice *d, int irq_num)
{
PCIVPBState *s = container_of(d->bus, PCIVPBState, pci_bus);
PCIVPBState *s = container_of(pci_get_bus(d), PCIVPBState, pci_bus);
if (s->irq_mapping == PCI_VPB_IRQMAP_BROKEN) {
/* Legacy broken IRQ mapping for compatibility with old and
@ -399,9 +399,9 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp)
memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32);
memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32);
pci_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci",
&s->pci_mem_space, &s->pci_io_space,
PCI_DEVFN(11, 0), TYPE_PCI_BUS);
pci_root_bus_new_inplace(&s->pci_bus, sizeof(s->pci_bus), dev, "pci",
&s->pci_mem_space, &s->pci_io_space,
PCI_DEVFN(11, 0), TYPE_PCI_BUS);
h->bus = &s->pci_bus;
object_initialize(&s->pci_dev, sizeof(s->pci_dev), TYPE_VERSATILE_PCI_HOST);

View File

@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci-host/xilinx-pcie.h"
@ -129,9 +130,9 @@ static void xilinx_pcie_host_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &pex->mmio);
sysbus_init_mmio(sbd, &s->mmio);
pci->bus = pci_register_bus(dev, s->name, xilinx_pcie_set_irq,
pci_swizzle_map_irq_fn, s, &s->mmio,
&s->io, 0, 4, TYPE_PCIE_BUS);
pci->bus = pci_register_root_bus(dev, s->name, xilinx_pcie_set_irq,
pci_swizzle_map_irq_fn, s, &s->mmio,
&s->io, 0, 4, TYPE_PCIE_BUS);
qdev_set_parent_bus(DEVICE(&s->root), BUS(pci->bus));
qdev_init_nofail(DEVICE(&s->root));
@ -267,24 +268,22 @@ static void xilinx_pcie_root_config_write(PCIDevice *d, uint32_t address,
}
}
static int xilinx_pcie_root_init(PCIDevice *dev)
static void xilinx_pcie_root_realize(PCIDevice *pci_dev, Error **errp)
{
BusState *bus = qdev_get_parent_bus(DEVICE(dev));
BusState *bus = qdev_get_parent_bus(DEVICE(pci_dev));
XilinxPCIEHost *s = XILINX_PCIE_HOST(bus->parent);
pci_set_word(dev->config + PCI_COMMAND,
pci_set_word(pci_dev->config + PCI_COMMAND,
PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
pci_set_word(dev->config + PCI_MEMORY_BASE, s->mmio_base >> 16);
pci_set_word(dev->config + PCI_MEMORY_LIMIT,
pci_set_word(pci_dev->config + PCI_MEMORY_BASE, s->mmio_base >> 16);
pci_set_word(pci_dev->config + PCI_MEMORY_LIMIT,
((s->mmio_base + s->mmio_size - 1) >> 16) & 0xfff0);
pci_bridge_initfn(dev, TYPE_PCI_BUS);
pci_bridge_initfn(pci_dev, TYPE_PCI_BUS);
if (pcie_endpoint_cap_v1_init(dev, 0x80) < 0) {
hw_error("Failed to initialize PCIe capability");
if (pcie_endpoint_cap_v1_init(pci_dev, 0x80) < 0) {
error_setg(errp, "Failed to initialize PCIe capability");
}
return 0;
}
static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data)
@ -300,7 +299,7 @@ static void xilinx_pcie_root_class_init(ObjectClass *klass, void *data)
k->class_id = PCI_CLASS_BRIDGE_HOST;
k->is_express = true;
k->is_bridge = true;
k->init = xilinx_pcie_root_init;
k->realize = xilinx_pcie_root_realize;
k->exit = pci_bridge_exitfn;
dc->reset = pci_bridge_reset;
k->config_read = xilinx_pcie_root_config_read;

View File

@ -222,7 +222,7 @@ static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change)
{
PCIBus *bus;
for (;;) {
bus = pci_dev->bus;
bus = pci_get_bus(pci_dev);
irq_num = bus->map_irq(pci_dev, irq_num);
if (bus->set_irq)
break;
@ -331,31 +331,15 @@ static void pci_host_bus_register(DeviceState *host)
QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next);
}
PCIBus *pci_find_primary_bus(void)
{
PCIBus *primary_bus = NULL;
PCIHostState *host;
QLIST_FOREACH(host, &pci_host_bridges, next) {
if (primary_bus) {
/* We have multiple root buses, refuse to select a primary */
return NULL;
}
primary_bus = host->bus;
}
return primary_bus;
}
PCIBus *pci_device_root_bus(const PCIDevice *d)
{
PCIBus *bus = d->bus;
PCIBus *bus = pci_get_bus(d);
while (!pci_bus_is_root(bus)) {
d = bus->parent_dev;
assert(d != NULL);
bus = d->bus;
bus = pci_get_bus(d);
}
return bus;
@ -376,10 +360,10 @@ const char *pci_root_bus_path(PCIDevice *dev)
return rootbus->qbus.name;
}
static void pci_bus_init(PCIBus *bus, DeviceState *parent,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min)
static void pci_root_bus_init(PCIBus *bus, DeviceState *parent,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min)
{
assert(PCI_FUNC(devfn_min) == 0);
bus->devfn_min = devfn_min;
@ -403,25 +387,27 @@ bool pci_bus_is_root(PCIBus *bus)
return PCI_BUS_GET_CLASS(bus)->is_root(bus);
}
void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename)
{
qbus_create_inplace(bus, bus_size, typename, parent, name);
pci_root_bus_init(bus, parent, address_space_mem, address_space_io,
devfn_min);
}
PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename)
{
qbus_create_inplace(bus, bus_size, typename, parent, name);
pci_bus_init(bus, parent, address_space_mem, address_space_io, devfn_min);
}
PCIBus *pci_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename)
{
PCIBus *bus;
bus = PCI_BUS(qbus_create(typename, parent, name));
pci_bus_init(bus, parent, address_space_mem, address_space_io, devfn_min);
pci_root_bus_init(bus, parent, address_space_mem, address_space_io,
devfn_min);
return bus;
}
@ -435,17 +421,18 @@ void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0]));
}
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq, const char *typename)
PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq,
const char *typename)
{
PCIBus *bus;
bus = pci_bus_new(parent, name, address_space_mem,
address_space_io, devfn_min, typename);
bus = pci_root_bus_new(parent, name, address_space_mem,
address_space_io, devfn_min, typename);
pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
return bus;
}
@ -879,7 +866,7 @@ static void pci_config_free(PCIDevice *pci_dev)
static void do_pci_unregister_device(PCIDevice *pci_dev)
{
pci_dev->bus->devices[pci_dev->devfn] = NULL;
pci_get_bus(pci_dev)->devices[pci_dev->devfn] = NULL;
pci_config_free(pci_dev);
if (memory_region_is_mapped(&pci_dev->bus_master_enable_region)) {
@ -900,7 +887,7 @@ static uint16_t pci_req_id_cache_extract(PCIReqIDCache *cache)
result = pci_get_bdf(cache->dev);
break;
case PCI_REQ_ID_SECONDARY_BUS:
bus_n = pci_bus_num(cache->dev->bus);
bus_n = pci_dev_bus_num(cache->dev);
result = PCI_BUILD_BDF(bus_n, 0);
break;
default:
@ -930,9 +917,9 @@ static PCIReqIDCache pci_req_id_cache_get(PCIDevice *dev)
.type = PCI_REQ_ID_BDF,
};
while (!pci_bus_is_root(dev->bus)) {
while (!pci_bus_is_root(pci_get_bus(dev))) {
/* We are under PCI/PCIe bridges */
parent = dev->bus->parent_dev;
parent = pci_get_bus(dev)->parent_dev;
if (pci_is_express(parent)) {
if (pcie_cap_get_type(parent) == PCI_EXP_TYPE_PCI_BRIDGE) {
/* When we pass through PCIe-to-PCI/PCIX bridges, we
@ -975,7 +962,7 @@ static bool pci_bus_devfn_reserved(PCIBus *bus, int devfn)
}
/* -1 for devfn means auto assign */
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
const char *name, int devfn,
Error **errp)
{
@ -984,8 +971,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
PCIConfigWriteFunc *config_write = pc->config_write;
Error *local_err = NULL;
DeviceState *dev = DEVICE(pci_dev);
PCIBus *bus = pci_get_bus(pci_dev);
pci_dev->bus = bus;
/* Only pci bridges can be attached to extra PCI root buses */
if (pci_bus_is_root(bus) && bus->parent_dev && !pc->is_bridge) {
error_setg(errp,
@ -1139,8 +1126,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
r->type = type;
r->memory = memory;
r->address_space = type & PCI_BASE_ADDRESS_SPACE_IO
? pci_dev->bus->address_space_io
: pci_dev->bus->address_space_mem;
? pci_get_bus(pci_dev)->address_space_io
: pci_get_bus(pci_dev)->address_space_mem;
wmask = ~(size - 1);
if (region_num == PCI_ROM_SLOT) {
@ -1182,21 +1169,23 @@ static void pci_update_vga(PCIDevice *pci_dev)
void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
MemoryRegion *io_lo, MemoryRegion *io_hi)
{
PCIBus *bus = pci_get_bus(pci_dev);
assert(!pci_dev->has_vga);
assert(memory_region_size(mem) == QEMU_PCI_VGA_MEM_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_MEM] = mem;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_mem,
memory_region_add_subregion_overlap(bus->address_space_mem,
QEMU_PCI_VGA_MEM_BASE, mem, 1);
assert(memory_region_size(io_lo) == QEMU_PCI_VGA_IO_LO_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO] = io_lo;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
memory_region_add_subregion_overlap(bus->address_space_io,
QEMU_PCI_VGA_IO_LO_BASE, io_lo, 1);
assert(memory_region_size(io_hi) == QEMU_PCI_VGA_IO_HI_SIZE);
pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI] = io_hi;
memory_region_add_subregion_overlap(pci_dev->bus->address_space_io,
memory_region_add_subregion_overlap(bus->address_space_io,
QEMU_PCI_VGA_IO_HI_BASE, io_hi, 1);
pci_dev->has_vga = true;
@ -1205,15 +1194,17 @@ void pci_register_vga(PCIDevice *pci_dev, MemoryRegion *mem,
void pci_unregister_vga(PCIDevice *pci_dev)
{
PCIBus *bus = pci_get_bus(pci_dev);
if (!pci_dev->has_vga) {
return;
}
memory_region_del_subregion(pci_dev->bus->address_space_mem,
memory_region_del_subregion(bus->address_space_mem,
pci_dev->vga_regions[QEMU_PCI_VGA_MEM]);
memory_region_del_subregion(pci_dev->bus->address_space_io,
memory_region_del_subregion(bus->address_space_io,
pci_dev->vga_regions[QEMU_PCI_VGA_IO_LO]);
memory_region_del_subregion(pci_dev->bus->address_space_io,
memory_region_del_subregion(bus->address_space_io,
pci_dev->vga_regions[QEMU_PCI_VGA_IO_HI]);
pci_dev->has_vga = false;
}
@ -1316,7 +1307,7 @@ static void pci_update_mappings(PCIDevice *d)
/* now do the real mapping */
if (r->addr != PCI_BAR_UNMAPPED) {
trace_pci_update_mappings_del(d, pci_bus_num(d->bus),
trace_pci_update_mappings_del(d, pci_dev_bus_num(d),
PCI_SLOT(d->devfn),
PCI_FUNC(d->devfn),
i, r->addr, r->size);
@ -1324,7 +1315,7 @@ static void pci_update_mappings(PCIDevice *d)
}
r->addr = new_addr;
if (r->addr != PCI_BAR_UNMAPPED) {
trace_pci_update_mappings_add(d, pci_bus_num(d->bus),
trace_pci_update_mappings_add(d, pci_dev_bus_num(d),
PCI_SLOT(d->devfn),
PCI_FUNC(d->devfn),
i, r->addr, r->size);
@ -1443,9 +1434,9 @@ PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin)
PCIBus *bus;
do {
bus = dev->bus;
pin = bus->map_irq(dev, pin);
dev = bus->parent_dev;
bus = pci_get_bus(dev);
pin = bus->map_irq(dev, pin);
dev = bus->parent_dev;
} while (dev);
if (!bus->route_intx_to_irq) {
@ -2015,7 +2006,6 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
PCIDevice *pci_dev = (PCIDevice *)qdev;
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev);
Error *local_err = NULL;
PCIBus *bus;
bool is_default_rom;
/* initialize cap_present for pci_is_express() and pci_config_size() */
@ -2023,8 +2013,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS;
}
bus = PCI_BUS(qdev_get_parent_bus(qdev));
pci_dev = do_pci_register_device(pci_dev, bus,
pci_dev = do_pci_register_device(pci_dev,
object_get_typename(OBJECT(qdev)),
pci_dev->devfn, errp);
if (pci_dev == NULL)
@ -2317,7 +2306,7 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
error_setg(errp, "%s:%02x:%02x.%x "
"Attempt to add PCI capability %x at offset "
"%x overlaps existing capability %x at offset %x",
pci_root_bus_path(pdev), pci_bus_num(pdev->bus),
pci_root_bus_path(pdev), pci_dev_bus_num(pdev),
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
cap_id, offset, overlapping_cap, i);
return -EINVAL;
@ -2381,7 +2370,7 @@ static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent)
monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, "
"pci id %04x:%04x (sub %04x:%04x)\n",
indent, "", ctxt, pci_bus_num(d->bus),
indent, "", ctxt, pci_dev_bus_num(d),
PCI_SLOT(d->devfn), PCI_FUNC(d->devfn),
pci_get_word(d->config + PCI_VENDOR_ID),
pci_get_word(d->config + PCI_DEVICE_ID),
@ -2464,7 +2453,7 @@ static char *pcibus_get_dev_path(DeviceState *dev)
/* Calculate # of slots on path between device and root. */;
slot_depth = 0;
for (t = d; t; t = t->bus->parent_dev) {
for (t = d; t; t = pci_get_bus(t)->parent_dev) {
++slot_depth;
}
@ -2479,7 +2468,7 @@ static char *pcibus_get_dev_path(DeviceState *dev)
/* Fill in slot numbers. We walk up from device to root, so need to print
* them in the reverse order, last to first. */
p = path + path_len;
for (t = d; t; t = t->bus->parent_dev) {
for (t = d; t; t = pci_get_bus(t)->parent_dev) {
p -= slot_len;
s = snprintf(slot, sizeof slot, ":%02x.%x",
PCI_SLOT(t->devfn), PCI_FUNC(t->devfn));
@ -2527,12 +2516,12 @@ int pci_qdev_find_device(const char *id, PCIDevice **pdev)
MemoryRegion *pci_address_space(PCIDevice *dev)
{
return dev->bus->address_space_mem;
return pci_get_bus(dev)->address_space_mem;
}
MemoryRegion *pci_address_space_io(PCIDevice *dev)
{
return dev->bus->address_space_io;
return pci_get_bus(dev)->address_space_io;
}
static void pci_device_class_init(ObjectClass *klass, void *data)
@ -2560,11 +2549,11 @@ static void pci_device_class_base_init(ObjectClass *klass, void *data)
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev)
{
PCIBus *bus = PCI_BUS(dev->bus);
PCIBus *bus = pci_get_bus(dev);
PCIBus *iommu_bus = bus;
while(iommu_bus && !iommu_bus->iommu_fn && iommu_bus->parent_dev) {
iommu_bus = PCI_BUS(iommu_bus->parent_dev->bus);
iommu_bus = pci_get_bus(iommu_bus->parent_dev);
}
if (iommu_bus && iommu_bus->iommu_fn) {
return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, dev->devfn);
@ -2635,7 +2624,7 @@ void pci_bus_get_w64_range(PCIBus *bus, Range *range)
static bool pcie_has_upstream_port(PCIDevice *dev)
{
PCIDevice *parent_dev = pci_bridge_get_device(dev->bus);
PCIDevice *parent_dev = pci_bridge_get_device(pci_get_bus(dev));
/* Device associated with an upstream port.
* As there are several types of these, it's easier to check the
@ -2651,12 +2640,14 @@ static bool pcie_has_upstream_port(PCIDevice *dev)
PCIDevice *pci_get_function_0(PCIDevice *pci_dev)
{
PCIBus *bus = pci_get_bus(pci_dev);
if(pcie_has_upstream_port(pci_dev)) {
/* With an upstream PCIe port, we only support 1 device at slot 0 */
return pci_dev->bus->devices[0];
return bus->devices[0];
} else {
/* Other bus types might support multiple devices at slots 0-31 */
return pci_dev->bus->devices[PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 0)];
return bus->devices[PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 0)];
}
}

View File

@ -183,7 +183,7 @@ static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent,
static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
{
PCIDevice *pd = PCI_DEVICE(br);
PCIBus *parent = pd->bus;
PCIBus *parent = pci_get_bus(pd);
PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1);
uint16_t cmd = pci_get_word(pd->config + PCI_COMMAND);
@ -214,7 +214,7 @@ static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
{
PCIDevice *pd = PCI_DEVICE(br);
PCIBus *parent = pd->bus;
PCIBus *parent = pci_get_bus(pd);
memory_region_del_subregion(parent->address_space_io, &w->alias_io);
memory_region_del_subregion(parent->address_space_mem, &w->alias_mem);
@ -339,7 +339,7 @@ void pci_bridge_reset(DeviceState *qdev)
/* default qdev initialization function for PCI-to-PCI bridge */
void pci_bridge_initfn(PCIDevice *dev, const char *typename)
{
PCIBus *parent = dev->bus;
PCIBus *parent = pci_get_bus(dev);
PCIBridge *br = PCI_BRIDGE(dev);
PCIBus *sec_bus = &br->sec_bus;

View File

@ -155,7 +155,8 @@ pcie_endpoint_cap_common_init(PCIDevice *dev, uint8_t offset, uint8_t cap_size)
* a regular Endpoint type is exposed on a root complex. These
* should instead be Root Complex Integrated Endpoints.
*/
if (pci_bus_is_express(dev->bus) && pci_bus_is_root(dev->bus)) {
if (pci_bus_is_express(pci_get_bus(dev))
&& pci_bus_is_root(pci_get_bus(dev))) {
type = PCI_EXP_TYPE_RC_END;
}
@ -369,7 +370,7 @@ void pcie_cap_slot_hot_unplug_request_cb(HotplugHandler *hotplug_dev,
{
uint8_t *exp_cap;
PCIDevice *pci_dev = PCI_DEVICE(dev);
PCIBus *bus = pci_dev->bus;
PCIBus *bus = pci_get_bus(pci_dev);
pcie_cap_slot_hotplug_common(PCI_DEVICE(hotplug_dev), dev, &exp_cap, errp);

View File

@ -409,7 +409,7 @@ static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
*/
return;
}
dev = pci_bridge_get_device(dev->bus);
dev = pci_bridge_get_device(pci_get_bus(dev));
}
}
@ -1025,7 +1025,7 @@ static int do_pcie_aer_inject_error(Monitor *mon,
}
details->id = id;
details->root_bus = pci_root_bus_path(dev);
details->bus = pci_bus_num(dev->bus);
details->bus = pci_dev_bus_num(dev);
details->devfn = dev->devfn;
return 0;

View File

@ -314,9 +314,9 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq[i]);
}
b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
ppc4xx_pci_map_irq, s->irq, get_system_memory(),
get_system_io(), 0, 4, TYPE_PCI_BUS);
b = pci_register_root_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
ppc4xx_pci_map_irq, s->irq, get_system_memory(),
get_system_io(), 0, 4, TYPE_PCI_BUS);
h->bus = b;
pci_create_simple(b, 0, "ppc4xx-host-bridge");

View File

@ -505,7 +505,7 @@ static void rtas_ibm_get_config_addr_info2(PowerPCCPU *cpu,
goto param_error_exit;
}
rtas_st(rets, 1, (pci_bus_num(pdev->bus) << 16) + 1);
rtas_st(rets, 1, (pci_bus_num(pci_get_bus(pdev)) << 16) + 1);
break;
case RTAS_GET_PE_MODE:
rtas_st(rets, 1, RTAS_PE_MODE_SHARED);
@ -1621,10 +1621,10 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
&sphb->iowindow);
bus = pci_register_bus(dev, NULL,
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
bus = pci_register_root_bus(dev, NULL,
pci_spapr_set_irq, pci_spapr_map_irq, sphb,
&sphb->memspace, &sphb->iospace,
PCI_DEVFN(0, 0), PCI_NUM_PINS, TYPE_PCI_BUS);
phb->bus = bus;
qbus_set_hotplug_handler(BUS(phb->bus), DEVICE(sphb), NULL);

View File

@ -554,10 +554,10 @@ static int s390_pcihost_init(SysBusDevice *dev)
DPRINTF("host_init\n");
b = pci_register_bus(DEVICE(dev), NULL,
s390_pci_set_irq, s390_pci_map_irq, NULL,
get_system_memory(), get_system_io(), 0, 64,
TYPE_PCI_BUS);
b = pci_register_root_bus(DEVICE(dev), NULL,
s390_pci_set_irq, s390_pci_map_irq, NULL,
get_system_memory(), get_system_io(), 0, 64,
TYPE_PCI_BUS);
pci_setup_iommu(b, s390_pci_dma_iommu, s);
bus = BUS(b);
@ -680,10 +680,10 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
s->bus_no += 1;
pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1);
do {
pdev = pdev->bus->parent_dev;
pdev = pci_get_bus(pdev)->parent_dev;
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS,
s->bus_no, 1);
} while (pdev->bus && pci_bus_num(pdev->bus));
} while (pci_get_bus(pdev) && pci_dev_bus_num(pdev));
}
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
pdev = PCI_DEVICE(dev);
@ -692,7 +692,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
/* In the case the PCI device does not define an id */
/* we generate one based on the PCI address */
dev->id = g_strdup_printf("auto_%02x:%02x.%01x",
pci_bus_num(pdev->bus),
pci_dev_bus_num(pdev),
PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
}
@ -713,7 +713,7 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
}
pbdev->pdev = pdev;
pbdev->iommu = s390_pci_get_iommu(s, pdev->bus, pdev->devfn);
pbdev->iommu = s390_pci_get_iommu(s, pci_get_bus(pdev), pdev->devfn);
pbdev->iommu->pbdev = pbdev;
pbdev->state = ZPCI_FS_DISABLED;
@ -807,7 +807,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
pbdev->fh, pbdev->fid);
bus = pci_dev->bus;
bus = pci_get_bus(pci_dev);
devfn = pci_dev->devfn;
object_unparent(OBJECT(pci_dev));
s390_pci_msix_free(pbdev);

View File

@ -2372,7 +2372,7 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
if (!s->sas_addr) {
s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
s->sas_addr |= (pci_bus_num(dev->bus) << 16);
s->sas_addr |= (pci_dev_bus_num(dev) << 16);
s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
s->sas_addr |= PCI_FUNC(dev->devfn);
}

View File

@ -1312,7 +1312,7 @@ static void mptsas_scsi_realize(PCIDevice *dev, Error **errp)
if (!s->sas_addr) {
s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) |
IEEE_COMPANY_LOCALLY_ASSIGNED) << 36;
s->sas_addr |= (pci_bus_num(dev->bus) << 16);
s->sas_addr |= (pci_dev_bus_num(dev) << 16);
s->sas_addr |= (PCI_SLOT(dev->devfn) << 8);
s->sas_addr |= PCI_FUNC(dev->devfn);
}

View File

@ -1133,7 +1133,7 @@ pvscsi_realizefn(PCIDevice *pci_dev, Error **errp)
pvscsi_init_msi(s);
if (pci_is_express(pci_dev) && pci_bus_is_express(pci_dev->bus)) {
if (pci_is_express(pci_dev) && pci_bus_is_express(pci_get_bus(pci_dev))) {
pcie_endpoint_cap_init(pci_dev, PVSCSI_EXP_EP_OFFSET);
}

View File

@ -131,12 +131,12 @@ static int sh_pci_device_init(SysBusDevice *dev)
for (i = 0; i < 4; i++) {
sysbus_init_irq(dev, &s->irq[i]);
}
phb->bus = pci_register_bus(DEVICE(dev), "pci",
sh_pci_set_irq, sh_pci_map_irq,
s->irq,
get_system_memory(),
get_system_io(),
PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
sh_pci_set_irq, sh_pci_map_irq,
s->irq,
get_system_memory(),
get_system_io(),
PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
"sh_pci", 0x224);
memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",

View File

@ -95,6 +95,11 @@ static struct {
const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
} type4;
static struct {
size_t nvalues;
const char **values;
} type11;
static struct {
const char *loc_pfx, *bank, *manufacturer, *serial, *asset, *part;
uint16_t speed;
@ -282,6 +287,14 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = {
{ /* end of list */ }
};
static const QemuOptDesc qemu_smbios_type11_opts[] = {
{
.name = "value",
.type = QEMU_OPT_STRING,
.help = "OEM string data",
},
};
static const QemuOptDesc qemu_smbios_type17_opts[] = {
{
.name = "type",
@ -590,6 +603,27 @@ static void smbios_build_type_4_table(unsigned instance)
smbios_type4_count++;
}
static void smbios_build_type_11_table(void)
{
char count_str[128];
size_t i;
if (type11.nvalues == 0) {
return;
}
SMBIOS_BUILD_TABLE_PRE(11, 0xe00, true); /* required */
snprintf(count_str, sizeof(count_str), "%zu", type11.nvalues);
t->count = type11.nvalues;
for (i = 0; i < type11.nvalues; i++) {
SMBIOS_TABLE_SET_STR_LIST(11, type11.values[i]);
}
SMBIOS_BUILD_TABLE_POST;
}
#define ONE_KB ((ram_addr_t)1 << 10)
#define ONE_MB ((ram_addr_t)1 << 20)
#define ONE_GB ((ram_addr_t)1 << 30)
@ -832,6 +866,8 @@ void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
smbios_build_type_4_table(i);
}
smbios_build_type_11_table();
#define MAX_DIMM_SZ (16ll * ONE_GB)
#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \
: ((ram_size - 1) % MAX_DIMM_SZ) + 1)
@ -882,6 +918,38 @@ static void save_opt(const char **dest, QemuOpts *opts, const char *name)
}
}
struct opt_list {
const char *name;
size_t *ndest;
const char ***dest;
};
static int save_opt_one(void *opaque,
const char *name, const char *value,
Error **errp)
{
struct opt_list *opt = opaque;
if (!g_str_equal(name, opt->name)) {
return 0;
}
*opt->dest = g_renew(const char *, *opt->dest, (*opt->ndest) + 1);
(*opt->dest)[*opt->ndest] = value;
(*opt->ndest)++;
return 0;
}
static void save_opt_list(size_t *ndest, const char ***dest,
QemuOpts *opts, const char *name)
{
struct opt_list opt = {
name, ndest, dest,
};
qemu_opt_foreach(opts, save_opt_one, &opt, NULL);
}
void smbios_entry_add(QemuOpts *opts, Error **errp)
{
const char *val;
@ -1035,6 +1103,10 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
save_opt(&type4.asset, opts, "asset");
save_opt(&type4.part, opts, "part");
return;
case 11:
qemu_opts_validate(opts, qemu_smbios_type11_opts, &error_fatal);
save_opt_list(&type11.nvalues, &type11.values, opts, "value");
return;
case 17:
qemu_opts_validate(opts, qemu_smbios_type17_opts, &error_fatal);
save_opt(&type17.loc_pfx, opts, "loc_pfx");

View File

@ -63,6 +63,18 @@ extern unsigned smbios_table_cnt;
} \
} while (0)
#define SMBIOS_TABLE_SET_STR_LIST(tbl_type, value) \
do { \
int len = (value != NULL) ? strlen(value) + 1 : 0; \
if (len > 1) { \
smbios_tables = g_realloc(smbios_tables, \
smbios_tables_len + len); \
memcpy(smbios_tables + smbios_tables_len, value, len); \
smbios_tables_len += len; \
++str_index; \
} \
} while (0)
#define SMBIOS_BUILD_TABLE_POST \
do { \
size_t term_cnt, t_size; \

View File

@ -3416,7 +3416,7 @@ static void usb_xhci_realize(struct PCIDevice *dev, Error **errp)
PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
&xhci->mem);
if (pci_bus_is_express(dev->bus) ||
if (pci_bus_is_express(pci_get_bus(dev)) ||
xhci_get_flag(xhci, XHCI_FLAG_FORCE_PCIE_ENDCAP)) {
ret = pcie_endpoint_cap_init(dev, 0xa0);
assert(ret > 0);

View File

@ -1654,8 +1654,8 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
return -EINVAL;
}
if (!pci_bus_is_express(vdev->pdev.bus)) {
PCIBus *bus = vdev->pdev.bus;
if (!pci_bus_is_express(pci_get_bus(&vdev->pdev))) {
PCIBus *bus = pci_get_bus(&vdev->pdev);
PCIDevice *bridge;
/*
@ -1680,14 +1680,14 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
*/
while (!pci_bus_is_root(bus)) {
bridge = pci_bridge_get_device(bus);
bus = bridge->bus;
bus = pci_get_bus(bridge);
}
if (pci_bus_is_express(bus)) {
return 0;
}
} else if (pci_bus_is_root(vdev->pdev.bus)) {
} else if (pci_bus_is_root(pci_get_bus(&vdev->pdev))) {
/*
* On a Root Complex bus Endpoints become Root Complex Integrated
* Endpoints, which changes the type and clears the LNK & LNK2 fields.
@ -1890,7 +1890,7 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
uint8_t *config;
/* Only add extended caps if we have them and the guest can see them */
if (!pci_is_express(pdev) || !pci_bus_is_express(pdev->bus) ||
if (!pci_is_express(pdev) || !pci_bus_is_express(pci_get_bus(pdev)) ||
!pci_get_long(pdev->config + PCI_CONFIG_SPACE_SIZE)) {
return;
}

View File

@ -1588,9 +1588,11 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
"neither legacy nor transitional device.");
return ;
}
/* legacy and transitional */
pci_set_word(config + PCI_SUBSYSTEM_VENDOR_ID,
pci_get_word(config + PCI_VENDOR_ID));
/*
* Legacy and transitional devices use specific subsystem IDs.
* Note that the subsystem vendor ID (config + PCI_SUBSYSTEM_VENDOR_ID)
* is set to PCI_SUBVENDOR_ID_REDHAT_QUMRANET by default.
*/
pci_set_word(config + PCI_SUBSYSTEM_ID, virtio_bus_get_vdev_id(bus));
} else {
/* pure virtio-1.0 */
@ -1708,8 +1710,8 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
VirtioPCIClass *k = VIRTIO_PCI_GET_CLASS(pci_dev);
bool pcie_port = pci_bus_is_express(pci_dev->bus) &&
!pci_bus_is_root(pci_dev->bus);
bool pcie_port = pci_bus_is_express(pci_get_bus(pci_dev)) &&
!pci_bus_is_root(pci_get_bus(pci_dev));
if (kvm_enabled() && !kvm_has_many_ioeventfds()) {
proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;

View File

@ -2469,7 +2469,7 @@ void GCC_FMT_ATTR(2, 3) virtio_error(VirtIODevice *vdev, const char *fmt, ...)
va_end(ap);
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
virtio_set_status(vdev, vdev->status | VIRTIO_CONFIG_S_NEEDS_RESET);
vdev->status = vdev->status | VIRTIO_CONFIG_S_NEEDS_RESET;
virtio_notify_config(vdev);
}

View File

@ -73,7 +73,7 @@ void xen_pt_log(const PCIDevice *d, const char *f, ...)
va_start(ap, f);
if (d) {
fprintf(stderr, "[%02x:%02x.%d] ", pci_bus_num(d->bus),
fprintf(stderr, "[%02x:%02x.%d] ", pci_dev_bus_num(d),
PCI_SLOT(d->devfn), PCI_FUNC(d->devfn));
}
vfprintf(stderr, f, ap);
@ -602,7 +602,7 @@ static void xen_pt_region_update(XenPCIPassthroughState *s,
}
args.type = d->io_regions[bar].type;
pci_for_each_device(d->bus, pci_bus_num(d->bus),
pci_for_each_device(pci_get_bus(d), pci_dev_bus_num(d),
xen_pt_check_bar_overlap, &args);
if (args.rc) {
XEN_PT_WARN(d, "Region: %d (addr: %#"FMT_PCIBUS
@ -695,7 +695,7 @@ xen_igd_passthrough_isa_bridge_create(XenPCIPassthroughState *s,
PCIDevice *d = &s->dev;
gpu_dev_id = dev->device_id;
igd_passthrough_isa_bridge_create(d->bus, gpu_dev_id);
igd_passthrough_isa_bridge_create(pci_get_bus(d), gpu_dev_id);
}
/* destroy. */
@ -711,7 +711,7 @@ static void xen_pt_destroy(PCIDevice *d) {
intx = xen_pt_pci_intx(s);
rc = xc_domain_unbind_pt_irq(xen_xc, xen_domid, machine_irq,
PT_IRQ_TYPE_PCI,
pci_bus_num(d->bus),
pci_dev_bus_num(d),
PCI_SLOT(s->dev.devfn),
intx,
0 /* isa_irq */);
@ -867,7 +867,7 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
uint8_t e_intx = xen_pt_pci_intx(s);
rc = xc_domain_bind_pt_pci_irq(xen_xc, xen_domid, machine_irq,
pci_bus_num(d->bus),
pci_dev_bus_num(d),
PCI_SLOT(d->devfn),
e_intx);
if (rc < 0) {

View File

@ -31,7 +31,6 @@
#define X86_IOMMU_GET_CLASS(obj) \
OBJECT_GET_CLASS(X86IOMMUClass, obj, TYPE_X86_IOMMU_DEVICE)
#define X86_IOMMU_PCI_DEVFN_MAX 256
#define X86_IOMMU_SID_INVALID (0xffff)
typedef struct X86IOMMUState X86IOMMUState;

View File

@ -23,7 +23,7 @@
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pcie_host.h"
#define TYPE_XILINX_PCIE_HOST "xilinx-pcie-host"

View File

@ -285,7 +285,6 @@ struct PCIDevice {
uint8_t *used;
/* the following fields are read only */
PCIBus *bus;
int32_t devfn;
/* Cached device to fetch requester ID from, to avoid the PCI
* tree walking every time we invoke PCI request (e.g.,
@ -400,26 +399,27 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
bool pci_bus_is_express(PCIBus *bus);
bool pci_bus_is_root(PCIBus *bus);
void pci_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename);
PCIBus *pci_root_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename);
PCIBus *pci_bus_new(DeviceState *parent, const char *name,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, const char *typename);
void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque, int nirq);
int pci_bus_get_irq_level(PCIBus *bus, int irq_num);
/* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
PCIBus *pci_register_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq, const char *typename);
PCIBus *pci_register_root_bus(DeviceState *parent, const char *name,
pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *irq_opaque,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
uint8_t devfn_min, int nirq,
const char *typename);
void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn);
PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin);
bool pci_intx_route_changed(PCIINTxRoute *old, PCIINTxRoute *new);
@ -434,7 +434,16 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
PCIDevice *pci_vga_init(PCIBus *bus);
static inline PCIBus *pci_get_bus(const PCIDevice *dev)
{
return PCI_BUS(qdev_get_parent_bus(DEVICE(dev)));
}
int pci_bus_num(PCIBus *s);
static inline int pci_dev_bus_num(const PCIDevice *dev)
{
return pci_bus_num(pci_get_bus(dev));
}
int pci_bus_numa_node(PCIBus *bus);
void pci_for_each_device(PCIBus *bus, int bus_num,
void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
@ -458,7 +467,6 @@ void pci_for_each_bus(PCIBus *bus,
pci_for_each_bus_depth_first(bus, NULL, fn, opaque);
}
PCIBus *pci_find_primary_bus(void);
PCIBus *pci_device_root_bus(const PCIDevice *d);
const char *pci_root_bus_path(PCIDevice *dev);
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
@ -739,7 +747,7 @@ static inline uint32_t pci_config_size(const PCIDevice *d)
static inline uint16_t pci_get_bdf(PCIDevice *dev)
{
return PCI_BUILD_BDF(pci_bus_num(dev->bus), dev->devfn);
return PCI_BUILD_BDF(pci_bus_num(pci_get_bus(dev)), dev->devfn);
}
uint16_t pci_requester_id(PCIDevice *dev);

View File

@ -27,6 +27,54 @@
#define QEMU_PCI_BRIDGE_H
#include "hw/pci/pci.h"
#include "hw/pci/pci_bus.h"
typedef struct PCIBridgeWindows PCIBridgeWindows;
/*
* Aliases for each of the address space windows that the bridge
* can forward. Mapped into the bridge's parent's address space,
* as subregions.
*/
struct PCIBridgeWindows {
MemoryRegion alias_pref_mem;
MemoryRegion alias_mem;
MemoryRegion alias_io;
/*
* When bridge control VGA forwarding is enabled, bridges will
* provide positive decode on the PCI VGA defined I/O port and
* MMIO ranges. When enabled forwarding is only qualified on the
* I/O and memory enable bits in the bridge command register.
*/
MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
};
#define TYPE_PCI_BRIDGE "base-pci-bridge"
#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE)
struct PCIBridge {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
/* private member */
PCIBus sec_bus;
/*
* Memory regions for the bridge's address spaces. These regions are not
* directly added to system_memory/system_io or its descendants.
* Bridge's secondary bus points to these, so that devices
* under the bridge see these regions as its address spaces.
* The regions are as large as the entire address space -
* they don't take into account any windows.
*/
MemoryRegion address_space_mem;
MemoryRegion address_space_io;
PCIBridgeWindows *windows;
pci_map_irq_fn map_irq;
const char *bus_name;
};
#define PCI_BRIDGE_DEV_PROP_CHASSIS_NR "chassis_nr"
#define PCI_BRIDGE_DEV_PROP_MSI "msi"

View File

@ -2,10 +2,10 @@
#define QEMU_PCI_BUS_H
/*
* PCI Bus and Bridge datastructures.
* PCI Bus datastructures.
*
* Do not access the following members directly;
* use accessor functions in pci.h, pci_bridge.h
* use accessor functions in pci.h
*/
typedef struct PCIBusClass {
@ -44,51 +44,4 @@ struct PCIBus {
Notifier machine_done;
};
typedef struct PCIBridgeWindows PCIBridgeWindows;
/*
* Aliases for each of the address space windows that the bridge
* can forward. Mapped into the bridge's parent's address space,
* as subregions.
*/
struct PCIBridgeWindows {
MemoryRegion alias_pref_mem;
MemoryRegion alias_mem;
MemoryRegion alias_io;
/*
* When bridge control VGA forwarding is enabled, bridges will
* provide positive decode on the PCI VGA defined I/O port and
* MMIO ranges. When enabled forwarding is only qualified on the
* I/O and memory enable bits in the bridge command register.
*/
MemoryRegion alias_vga[QEMU_PCI_VGA_NUM_REGIONS];
};
#define TYPE_PCI_BRIDGE "base-pci-bridge"
#define PCI_BRIDGE(obj) OBJECT_CHECK(PCIBridge, (obj), TYPE_PCI_BRIDGE)
struct PCIBridge {
/*< private >*/
PCIDevice parent_obj;
/*< public >*/
/* private member */
PCIBus sec_bus;
/*
* Memory regions for the bridge's address spaces. These regions are not
* directly added to system_memory/system_io or its descendants.
* Bridge's secondary bus points to these, so that devices
* under the bridge see these regions as its address spaces.
* The regions are as large as the entire address space -
* they don't take into account any windows.
*/
MemoryRegion address_space_mem;
MemoryRegion address_space_io;
PCIBridgeWindows *windows;
pci_map_irq_fn map_irq;
const char *bus_name;
};
#endif /* QEMU_PCI_BUS_H */

View File

@ -31,6 +31,7 @@ extern const PropertyInfo qdev_prop_vlan;
extern const PropertyInfo qdev_prop_pci_devfn;
extern const PropertyInfo qdev_prop_blocksize;
extern const PropertyInfo qdev_prop_pci_host_devaddr;
extern const PropertyInfo qdev_prop_uuid;
extern const PropertyInfo qdev_prop_arraylen;
extern const PropertyInfo qdev_prop_link;
@ -214,6 +215,14 @@ extern const PropertyInfo qdev_prop_link;
#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *)
#define DEFINE_PROP_UUID(_name, _state, _field) { \
.name = (_name), \
.info = &qdev_prop_uuid, \
.offset = offsetof(_state, _field) \
+ type_check(QemuUUID, typeof_field(_state, _field)), \
.set_default = true, \
}
#define DEFINE_PROP_END_OF_LIST() \
{}

View File

@ -195,6 +195,12 @@ struct smbios_type_4 {
uint16_t processor_family2;
} QEMU_PACKED;
/* SMBIOS type 11 - OEM strings */
struct smbios_type_11 {
struct smbios_structure_header header;
uint8_t count;
} QEMU_PACKED;
/* SMBIOS type 16 - Physical Memory Array (v2.7) */
struct smbios_type_16 {
struct smbios_structure_header header;

View File

@ -542,10 +542,10 @@ static inline void xen_map_pcidev(domid_t dom,
return;
}
trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev->bus),
trace_xen_map_pcidev(ioservid, pci_dev_bus_num(pci_dev),
PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
xendevicemodel_map_pcidev_to_ioreq_server(xen_dmod, dom, ioservid, 0,
pci_bus_num(pci_dev->bus),
pci_dev_bus_num(pci_dev),
PCI_SLOT(pci_dev->devfn),
PCI_FUNC(pci_dev->devfn));
}
@ -558,10 +558,10 @@ static inline void xen_unmap_pcidev(domid_t dom,
return;
}
trace_xen_unmap_pcidev(ioservid, pci_bus_num(pci_dev->bus),
trace_xen_unmap_pcidev(ioservid, pci_dev_bus_num(pci_dev),
PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
xendevicemodel_unmap_pcidev_from_ioreq_server(xen_dmod, dom, ioservid, 0,
pci_bus_num(pci_dev->bus),
pci_dev_bus_num(pci_dev),
PCI_SLOT(pci_dev->devfn),
PCI_FUNC(pci_dev->devfn));
}

View File

@ -22,14 +22,53 @@
static char disk[] = "tests/pxe-test-disk-XXXXXX";
static void test_pxe_one(const char *params, bool ipv6)
typedef struct testdef {
const char *machine; /* Machine type */
const char *model; /* NIC device model */
} testdef_t;
static testdef_t x86_tests[] = {
{ "pc", "e1000" },
{ "pc", "virtio-net-pci" },
{ "q35", "e1000e" },
{ "q35", "virtio-net-pci", },
{ NULL },
};
static testdef_t x86_tests_slow[] = {
{ "pc", "ne2k_pci", },
{ "pc", "i82550", },
{ "pc", "rtl8139" },
{ "pc", "vmxnet3" },
{ NULL },
};
static testdef_t ppc64_tests[] = {
{ "pseries", "spapr-vlan" },
{ "pseries", "virtio-net-pci", },
{ NULL },
};
static testdef_t ppc64_tests_slow[] = {
{ "pseries", "e1000" },
{ NULL },
};
static testdef_t s390x_tests[] = {
{ "s390-ccw-virtio", "virtio-net-ccw" },
{ NULL },
};
static void test_pxe_one(const testdef_t *test, bool ipv6)
{
char *args;
args = g_strdup_printf("-machine accel=kvm:tcg -nodefaults -boot order=n "
"-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,"
"ipv4=%s,ipv6=%s %s", disk, ipv6 ? "off" : "on",
ipv6 ? "on" : "off", params);
args = g_strdup_printf(
"-machine %s,accel=kvm:tcg -nodefaults -boot order=n "
"-netdev user,id=" NETNAME ",tftp=./,bootfile=%s,ipv4=%s,ipv6=%s "
"-device %s,bootindex=1,netdev=" NETNAME,
test->machine, disk, ipv6 ? "off" : "on", ipv6 ? "on" : "off",
test->model);
qtest_start(args);
boot_sector_test();
@ -39,22 +78,38 @@ static void test_pxe_one(const char *params, bool ipv6)
static void test_pxe_ipv4(gconstpointer data)
{
const char *model = data;
char *dev_arg;
const testdef_t *test = data;
dev_arg = g_strdup_printf("-device %s,netdev=" NETNAME, model);
test_pxe_one(dev_arg, false);
g_free(dev_arg);
test_pxe_one(test, false);
}
static void test_pxe_spapr_vlan(void)
static void test_pxe_ipv6(gconstpointer data)
{
test_pxe_one("-device spapr-vlan,netdev=" NETNAME, true);
const testdef_t *test = data;
test_pxe_one(test, true);
}
static void test_pxe_virtio_ccw(void)
static void test_batch(const testdef_t *tests, bool ipv6)
{
test_pxe_one("-device virtio-net-ccw,bootindex=1,netdev=" NETNAME, false);
int i;
for (i = 0; tests[i].machine; i++) {
const testdef_t *test = &tests[i];
char *testname;
testname = g_strdup_printf("pxe/ipv4/%s/%s",
test->machine, test->model);
qtest_add_data_func(testname, test, test_pxe_ipv4);
g_free(testname);
if (ipv6) {
testname = g_strdup_printf("pxe/ipv6/%s/%s",
test->machine, test->model);
qtest_add_data_func(testname, test, test_pxe_ipv6);
g_free(testname);
}
}
}
int main(int argc, char *argv[])
@ -69,23 +124,17 @@ int main(int argc, char *argv[])
g_test_init(&argc, &argv, NULL);
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
qtest_add_data_func("pxe/e1000", "e1000", test_pxe_ipv4);
qtest_add_data_func("pxe/virtio", "virtio-net-pci", test_pxe_ipv4);
test_batch(x86_tests, false);
if (g_test_slow()) {
qtest_add_data_func("pxe/ne2000", "ne2k_pci", test_pxe_ipv4);
qtest_add_data_func("pxe/eepro100", "i82550", test_pxe_ipv4);
qtest_add_data_func("pxe/pcnet", "pcnet", test_pxe_ipv4);
qtest_add_data_func("pxe/rtl8139", "rtl8139", test_pxe_ipv4);
qtest_add_data_func("pxe/vmxnet3", "vmxnet3", test_pxe_ipv4);
test_batch(x86_tests_slow, false);
}
} else if (strcmp(arch, "ppc64") == 0) {
qtest_add_func("pxe/spapr-vlan", test_pxe_spapr_vlan);
test_batch(ppc64_tests, g_test_slow());
if (g_test_slow()) {
qtest_add_data_func("pxe/virtio", "virtio-net-pci", test_pxe_ipv4);
qtest_add_data_func("pxe/e1000", "e1000", test_pxe_ipv4);
test_batch(ppc64_tests_slow, true);
}
} else if (g_str_equal(arch, "s390x")) {
qtest_add_func("pxe/virtio-ccw", test_pxe_virtio_ccw);
test_batch(s390x_tests, g_test_slow());
}
ret = g_test_run();
boot_sector_cleanup(disk);

View File

@ -674,6 +674,30 @@ static void pci_hotplug(void)
qtest_shutdown(qs);
}
/*
* Check that setting the vring addr on a non-existent virtqueue does
* not crash.
*/
static void test_nonexistent_virtqueue(void)
{
QPCIBar bar0;
QOSState *qs;
QPCIDevice *dev;
qs = pci_test_start();
dev = qpci_device_find(qs->pcibus, QPCI_DEVFN(4, 0));
g_assert(dev != NULL);
qpci_device_enable(dev);
bar0 = qpci_iomap(dev, 0, NULL);
qpci_io_writeb(dev, bar0, VIRTIO_PCI_QUEUE_SEL, 2);
qpci_io_writel(dev, bar0, VIRTIO_PCI_QUEUE_PFN, 1);
g_free(dev);
qtest_shutdown(qs);
}
static void mmio_basic(void)
{
QVirtioMMIODevice *dev;
@ -724,6 +748,7 @@ int main(int argc, char **argv)
qtest_add_func("/virtio/blk/pci/basic", pci_basic);
qtest_add_func("/virtio/blk/pci/indirect", pci_indirect);
qtest_add_func("/virtio/blk/pci/config", pci_config);
qtest_add_func("/virtio/blk/pci/nxvirtq", test_nonexistent_virtqueue);
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
qtest_add_func("/virtio/blk/pci/msix", pci_msix);
qtest_add_func("/virtio/blk/pci/idx", pci_idx);