bhyve: ignore low bits of CFGADR

Bhyve could emulate wrong PCI registers.
In the best case, the guest reads wrong registers and the device driver would
report some errors.
In the worst case, the guest writes to wrong PCI registers and could brick
hardware when using PCI passthrough.

According to Intels specification, low bits of CFGADR should be
ignored. Some OS like linux may rely on it. Otherwise, bhyve could
emulate a wrong PCI register.

E.g.
If linux would like to read 2 bytes from offset 0x02, following would
happen.
linux:
	outl 0x80000002 at CFGADR
	inw  at CFGDAT + 2
bhyve:
	cfgoff = 0x80000002 & 0xFF = 0x02
	coff   = cfgoff + (port - CFGDAT) = 0x02 + 0x02 = 0x04
Bhyve would emulate the register at offset 0x04 not 0x02.

Reviewed By: #bhyve, grehan
Differential Revision: https://reviews.freebsd.org/D31819
Sponsored by:	       Beckhoff Automation GmbH & Co. KG
This commit is contained in:
Corvin Köhne 2021-10-15 09:25:54 +02:00 committed by Emmanuel Vadot
parent 6495766acf
commit 1b0e2f0b60

View File

@ -2018,7 +2018,7 @@ pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
} else {
x = *eax;
cfgenable = (x & CONF1_ENABLE) == CONF1_ENABLE;
cfgoff = x & PCI_REGMAX;
cfgoff = (x & PCI_REGMAX) & ~0x03;
cfgfunc = (x >> 8) & PCI_FUNCMAX;
cfgslot = (x >> 11) & PCI_SLOTMAX;
cfgbus = (x >> 16) & PCI_BUSMAX;