@@ -1244,30 +1244,38 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos)
#endif
#endif
-static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev, uint32_t address,
+static void assigned_device_pci_cap_write_config(PCIDevice *pci_dev,
+ uint8_t cap_id,
+ uint32_t address,
uint32_t val, int len)
{
- AssignedDevice *assigned_dev = container_of(pci_dev, AssignedDevice, dev);
+ pci_default_cap_write_config(pci_dev, cap_id, address, val, len);
- pci_default_cap_write_config(pci_dev, address, val, len);
+ switch (cap_id) {
#ifdef KVM_CAP_IRQ_ROUTING
+ case PCI_CAP_ID_MSI:
#ifdef KVM_CAP_DEVICE_MSI
- if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSI) {
- int pos = pci_find_capability(pci_dev, PCI_CAP_ID_MSI);
- if (ranges_overlap(address, len, pos + PCI_MSI_FLAGS, 1)) {
- assigned_dev_update_msi(pci_dev, pos + PCI_MSI_FLAGS);
+ {
+ uint8_t cap = pci_find_capability(pci_dev, cap_id);
+ if (ranges_overlap(address - cap, len, PCI_MSI_FLAGS, 1)) {
+ assigned_dev_update_msi(pci_dev, cap + PCI_MSI_FLAGS);
+ }
}
- }
#endif
+ break;
+
+ case PCI_CAP_ID_MSIX:
#ifdef KVM_CAP_DEVICE_MSIX
- if (assigned_dev->cap.available & ASSIGNED_DEVICE_CAP_MSIX) {
- int pos = pci_find_capability(pci_dev, PCI_CAP_ID_MSIX);
- if (ranges_overlap(address, len, pos + PCI_MSIX_FLAGS + 1, 1)) {
- assigned_dev_update_msix(pci_dev, pos + PCI_MSIX_FLAGS);
- }
- }
+ {
+ uint8_t cap = pci_find_capability(pci_dev, cap_id);
+ if (ranges_overlap(address - cap, len, PCI_MSIX_FLAGS + 1, 1)) {
+ assigned_dev_update_msix(pci_dev, cap + PCI_MSIX_FLAGS);
+ }
+ }
#endif
+ break;
#endif
+ }
return;
}
@@ -1168,10 +1168,11 @@ static uint32_t pci_read_config(PCIDevice *d,
uint32_t pci_default_read_config(PCIDevice *d,
uint32_t address, int len)
{
+ uint8_t cap_id;
assert(len == 1 || len == 2 || len == 4);
- if (pci_access_cap_config(d, address, len)) {
- return d->cap.config_read(d, address, len);
+ if ((cap_id = pci_access_cap_config(d, address, len))) {
+ return d->cap.config_read(d, cap_id, address, len);
}
return pci_read_config(d, address, len);
@@ -1193,13 +1194,13 @@ int pci_access_cap_config(PCIDevice *pci_dev, uint32_t address, int len)
return pci_dev->cap_map[address];
}
-uint32_t pci_default_cap_read_config(PCIDevice *pci_dev,
+uint32_t pci_default_cap_read_config(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, int len)
{
return pci_read_config(pci_dev, address, len);
}
-void pci_default_cap_write_config(PCIDevice *pci_dev,
+void pci_default_cap_write_config(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, uint32_t val, int len)
{
pci_write_config(pci_dev, address, val, len);
@@ -1208,9 +1209,10 @@ void pci_default_cap_write_config(PCIDevice *pci_dev,
void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
{
int was_irq_disabled = pci_irq_disabled(d);
+ uint8_t cap_id;
- if (pci_access_cap_config(d, addr, l)) {
- d->cap.config_write(d, addr, val, l);
+ if ((cap_id = pci_access_cap_config(d, addr, l))) {
+ d->cap.config_write(d, cap_id, addr, val, l);
return;
}
@@ -83,9 +83,9 @@ typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type);
typedef int PCIUnregisterFunc(PCIDevice *pci_dev);
-typedef void PCICapConfigWriteFunc(PCIDevice *pci_dev,
+typedef void PCICapConfigWriteFunc(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, uint32_t val, int len);
-typedef uint32_t PCICapConfigReadFunc(PCIDevice *pci_dev,
+typedef uint32_t PCICapConfigReadFunc(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, int len);
typedef struct PCIIORegion {
@@ -245,9 +245,9 @@ void pci_default_write_config(PCIDevice *d,
uint32_t address, uint32_t val, int len);
void pci_device_save(PCIDevice *s, QEMUFile *f);
int pci_device_load(PCIDevice *s, QEMUFile *f);
-uint32_t pci_default_cap_read_config(PCIDevice *pci_dev,
+uint32_t pci_default_cap_read_config(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, int len);
-void pci_default_cap_write_config(PCIDevice *pci_dev,
+void pci_default_cap_write_config(PCIDevice *pci_dev, uint8_t cap_id,
uint32_t address, uint32_t val, int len);
int pci_access_cap_config(PCIDevice *pci_dev, uint32_t address, int len);