From 296b649ae90a1dfd5561c86708d2dfa22463ec8a Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 11 Jun 2019 15:06:52 +0800 Subject: [PATCH] ACRN/HV: emulated pcicfg uses the aligned offset to fix the unaligned pci_cfg access When the SOS kernel/pre-launched OS access the 0xCF8/0xCFC, it will cause the vm-exit and then the hypervisor tries to emulate the PCI_cfg access. 0xCF8 write: The bdf/reg is captured. cache_reg = value & (0xFF); 0xCFC-0xCFF read/write: offset = address - 0xCFC. Then cached_reg + offset is used as the offset to access the pci_cfg. If the aligned reg is passed in 0xCF8 register, it can work well. But when the unaligned reg is passed in 0xCF8 register, the cached_reg + offset will cause that the incorrect pci_cfg offset is accessed. For example: The cached_reg = 0x02(Device_ID offset) based on the value passed from 0xCF8 offset = 2 based on 0xCFC-0xCFF address. Then cached_reg + offset is used as the offset(PCI_CMD_REG) In fact the unaligned reg can work well on the real HW. So the cached_reg should be aligned to handle the unaligned reg passed in 0xCF8 reg. Tracked-On: #3249 Signed-off-by: Zhao Yakui Reviewed-by: Yin Fengwei --- hypervisor/dm/vpci/vpci.c | 2 +- hypervisor/include/hw/pci.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hypervisor/dm/vpci/vpci.c b/hypervisor/dm/vpci/vpci.c index ca20da30d..f2777ecbd 100644 --- a/hypervisor/dm/vpci/vpci.c +++ b/hypervisor/dm/vpci/vpci.c @@ -85,7 +85,7 @@ static bool pci_cfgaddr_io_write(struct acrn_vm *vm, uint16_t addr, size_t bytes if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) { pi->cached_bdf.value = (uint16_t)(val >> 8U); - pi->cached_reg = val & PCI_REGMAX; + pi->cached_reg = val & PCI_REGMASK; pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE); } diff --git a/hypervisor/include/hw/pci.h b/hypervisor/include/hw/pci.h index d4eb6e47e..dc44ba8af 100644 --- a/hypervisor/include/hw/pci.h +++ b/hypervisor/include/hw/pci.h @@ -49,6 +49,7 @@ #define PCI_FUNCMAX 0x7U #define PCI_BAR_COUNT 0x6U #define PCI_REGMAX 0xFFU +#define PCI_REGMASK 0xFCU /* I/O ports */ #define PCI_CONFIG_ADDR 0xCF8U