@@ -168,6 +168,9 @@ static bool virtio_pci__io_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 p
vpci = vdev->virtio;
offset = port - vpci->port_addr;
+ if (!(vpci->pci_hdr.command & PCI_COMMAND_IO))
+ return true;
+
return virtio_pci__data_in(vcpu, vdev, offset, data, size);
}
@@ -328,6 +331,9 @@ static bool virtio_pci__io_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16
vpci = vdev->virtio;
offset = port - vpci->port_addr;
+ if (!(vpci->pci_hdr.command & PCI_COMMAND_IO))
+ return true;
+
return virtio_pci__data_out(vcpu, vdev, offset, data, size);
}
@@ -346,6 +352,9 @@ static void virtio_pci__msix_mmio_callback(struct kvm_cpu *vcpu,
int vecnum;
size_t offset;
+ if (!(vpci->pci_hdr.command & PCI_COMMAND_MEMORY))
+ return;
+
if (addr > vpci->msix_io_block + PCI_IO_SIZE) {
if (is_write)
return;
@@ -443,6 +452,9 @@ static void virtio_pci__io_mmio_callback(struct kvm_cpu *vcpu,
struct virtio_device *vdev = ptr;
struct virtio_pci *vpci = vdev->virtio;
+ if (!(vpci->pci_hdr.command & PCI_COMMAND_MEMORY))
+ return;
+
if (!is_write)
virtio_pci__data_in(vcpu, vdev, addr - vpci->mmio_addr,
data, len);
@@ -483,7 +495,8 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
vpci->pci_hdr = (struct pci_device_header) {
.vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
.device_id = cpu_to_le16(device_id),
- .command = PCI_COMMAND_IO | PCI_COMMAND_MEMORY,
+ /* The Command register is 0 on RST. */
+ .command = 0,
.header_type = PCI_HEADER_TYPE_NORMAL,
.revision_id = 0,
.class[0] = class & 0xff,
A device's response to memory or I/O accesses is disabled when Memory Space, respectively I/O Space, is set to 0 in the Command register. According to the PCI Local Bus Specification Revision 3.0, those two bits reset to 0. Let's respect the specifiction, so set Command and I/O Space to 0 on reset, and ignore accesses to a device's respective regions when they are disabled. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- virtio/pci.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)