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 <yakui.zhao@intel.com>
Reviewed-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
Zhao Yakui 2019-06-11 15:06:52 +08:00 committed by wenlingz
parent 2321fcdf78
commit 296b649ae9
2 changed files with 2 additions and 1 deletions

View File

@ -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)) { if ((addr == (uint16_t)PCI_CONFIG_ADDR) && (bytes == 4U)) {
pi->cached_bdf.value = (uint16_t)(val >> 8U); 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); pi->cached_enable = ((val & PCI_CFG_ENABLE) == PCI_CFG_ENABLE);
} }

View File

@ -49,6 +49,7 @@
#define PCI_FUNCMAX 0x7U #define PCI_FUNCMAX 0x7U
#define PCI_BAR_COUNT 0x6U #define PCI_BAR_COUNT 0x6U
#define PCI_REGMAX 0xFFU #define PCI_REGMAX 0xFFU
#define PCI_REGMASK 0xFCU
/* I/O ports */ /* I/O ports */
#define PCI_CONFIG_ADDR 0xCF8U #define PCI_CONFIG_ADDR 0xCF8U