diff --git a/hypervisor/dm/vpci/pci_pt.c b/hypervisor/dm/vpci/pci_pt.c index 58c2707f7..9f14bad8d 100644 --- a/hypervisor/dm/vpci/pci_pt.c +++ b/hypervisor/dm/vpci/pci_pt.c @@ -379,7 +379,24 @@ static void init_bars(struct pci_vdev *vdev, bool is_sriov_bar) if (is_pci_reserved_bar(vbar)) { continue; } - mask = (is_pci_io_bar(vbar)) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK; + + if (is_pci_io_bar(vbar)) { + if (lo & ~IO_SPACE_BITMASK) { + /* + * Some buggy x86 BIOS may program an invalid I/O BAR whose upper 16 bits are not zero. + * Such I/O BAR is not addressable on x86 platforms. Skip it when initializing the + * virtual PCI function as I/O BAR reprogramming in VM is currently unsupported. + */ + pr_warn("%s: %02x:%02x.%x: IO BAR%d value 0x%08x has invalid bits, IO_SPACE_BITMASK " + "is 0x%08x, Ignore this BAR in vdev", + __func__, vdev->bdf.bits.b, vdev->bdf.bits.d, vdev->bdf.bits.f, idx, lo, + IO_SPACE_BITMASK); + continue; + } + mask = PCI_BASE_ADDRESS_IO_MASK; + } else { + mask = PCI_BASE_ADDRESS_MEM_MASK; + } vbar->base_hpa = (uint64_t)lo & mask; if (is_pci_mem64lo_bar(vbar)) { diff --git a/hypervisor/include/arch/x86/asm/io.h b/hypervisor/include/arch/x86/asm/io.h index 42bf87bf3..9bf1f62ce 100644 --- a/hypervisor/include/arch/x86/asm/io.h +++ b/hypervisor/include/arch/x86/asm/io.h @@ -9,6 +9,9 @@ #include +/* X86 architecture only supports 16 bits IO space */ +#define IO_SPACE_BITMASK 0xffffU + /* Write 1 byte to specified I/O port */ static inline void pio_write8(uint8_t value, uint16_t port) {