mirror of https://gitee.com/openkylin/qemu.git
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:
commit
36b5e43af8
|
@ -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
|
||||
-------------
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
143
hw/pci/pci.c
143
hw/pci/pci.c
|
@ -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)];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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() \
|
||||
{}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue