summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2011-04-29 11:05:30 +0200
committerMarcelo Tosatti <mtosatti@redhat.com>2011-05-03 16:13:59 -0300
commitb97c4d0d9c0e1d302f4918823e6a321754217eb2 (patch)
treeb237455034387722f9c4b037edc3fddf0090764a
parent8b24dce045c96f1b4e22c948697d6ccfd7152147 (diff)
pci-assign: Fix dword read at PCI_COMMAND
If we emulate the command register, we must only read its content from the shadow config space. For dword read of both PCI_COMMAND and PCI_STATUS, at least the latter must be read from the device. For simplicity reasons and as the code path is not considered performance critical for the affected SRIOV devices, the fix performes device access to the command word unconditionally, even if emulation is enabled and only that word is read. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Acked-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--hw/device-assignment.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/hw/device-assignment.c b/hw/device-assignment.c
index ea1d7f1e5..cea072ea6 100644
--- a/hw/device-assignment.c
+++ b/hw/device-assignment.c
@@ -482,14 +482,11 @@ static uint32_t assigned_dev_pci_read_config(PCIDevice *d, uint32_t address,
/*
* Catch access to
* - vendor & device ID
- * - command register (if emulation needed)
* - base address registers
* - ROM base address & capability pointer
* - interrupt line & pin
*/
if (ranges_overlap(address, len, PCI_VENDOR_ID, 4) ||
- (pci_dev->need_emulate_cmd &&
- ranges_overlap(address, len, PCI_COMMAND, 2)) ||
ranges_overlap(address, len, PCI_BASE_ADDRESS_0, 24) ||
ranges_overlap(address, len, PCI_ROM_ADDRESS, 5) ||
ranges_overlap(address, len, PCI_INTERRUPT_LINE, 2)) {
@@ -521,6 +518,11 @@ do_log:
DEBUG("(%x.%x): address=%04x val=0x%08x len=%d\n",
(d->devfn >> 3) & 0x1F, (d->devfn & 0x7), address, val, len);
+ if (pci_dev->need_emulate_cmd) {
+ val = merge_bits(val, pci_default_read_config(d, address, len),
+ address, len, PCI_COMMAND, 0xffff);
+ }
+
if (!pci_dev->cap.available) {
/* kill the special capabilities */
if (address == PCI_COMMAND && len == 4) {