From ceb197c9932cf7c7c23313725114ea3ac413d678 Mon Sep 17 00:00:00 2001 From: Junming Liu Date: Fri, 10 Jan 2020 14:56:41 +0000 Subject: [PATCH] dm:keep pci bar property unchanged when updating pci bar address When update pci bar addr, DM may change the bar property by func pci_cfgrw. PCI spec chapter 'Base Addresses' shows bits 0~3 are readonly of memeory space BAR, so this change won't happen. This patch ensures pci bar property unchanged when update pci bar addr. Tracked-On: #4282 Signed-off-by: Junming Liu Reviewed-by: Zhao Yakui Reviewed-by: Shuo A Liu Acked-by: Yu Wang --- devicemodel/hw/pci/core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/devicemodel/hw/pci/core.c b/devicemodel/hw/pci/core.c index 7c1db8910..2527366b1 100644 --- a/devicemodel/hw/pci/core.c +++ b/devicemodel/hw/pci/core.c @@ -2236,6 +2236,7 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, int idx, needcfg; uint64_t addr, bar, mask; bool decode, ignore_reg_unreg = false; + uint8_t mmio_bar_prop; bi = pci_businfo[bus]; if (bi != NULL) { @@ -2342,6 +2343,11 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, } } + /* save the bar property for MMIO pci bar. */ + mmio_bar_prop = pci_get_cfgdata32(dev, PCIR_BAR(idx)) & + (PCIM_BAR_SPACE | PCIM_BAR_MEM_TYPE | + PCIM_BAR_MEM_PREFETCH); + switch (dev->bar[idx].type) { case PCIBAR_NONE: dev->bar[idx].addr = bar = 0; @@ -2361,7 +2367,8 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, break; case PCIBAR_MEM32: addr = bar = *eax & mask; - bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; + /* Restore the readonly fields for mmio bar */ + bar |= mmio_bar_prop; if (addr != dev->bar[idx].addr) { update_bar_address(ctx, dev, addr, idx, PCIBAR_MEM32, @@ -2370,8 +2377,8 @@ pci_cfgrw(struct vmctx *ctx, int vcpu, int in, int bus, int slot, int func, break; case PCIBAR_MEM64: addr = bar = *eax & mask; - bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | - PCIM_BAR_MEM_PREFETCH; + /* Restore the readonly fields for mmio bar */ + bar |= mmio_bar_prop; if (addr != (uint32_t)dev->bar[idx].addr) { update_bar_address(ctx, dev, addr, idx, PCIBAR_MEM64,