Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Apr 2024 18:03:11 -0400
From:      Mark Johnston <markj@freebsd.org>
To:        freebsd-virtualization@freebsd.org
Subject:   PCI BAR registration overlap
Message-ID:  <ZimBn5Cv0ippsgTj@nuc>

next in thread | raw e-mail | index | archive | help
I've been working on porting bhyvectl and vmrun.sh to arm64, as the
initial arm64 bhyve port has landed in main.  In the process I
discovered a problem with bhyve's handling of BARs that I'd appreciate
some help with.

Suppose I configure a VM with a virtio-blk and virtio-net device.  Both
register BAR 0 as an I/O BAR with sizes of 128 and 64, respectively, and
bhyve puts them at 0xdf000000 and 0xdf000080.  If the network device is
PCI device 2 and the block device is device 3, which happens
automatically when using vmrun.sh, then for some reason u-boot suffles
them around: it unmaps the network device BAR at 0xdf000080, then maps
it at 0xdf000000, and then it unmaps the block device BAR at 0xdf000000,
and puts it at 0xdf000080.  I don't know yet why it does this; if the
PCI device numbers are swapped then the BARs aren't moved around.

This behaviour interacts with an oddity of bhyve's register_mem_init():
when u-boot maps the network device BAR at 0xdf000000,
register_mem_init() does a lookup, finds that a MMIO region is there,
and silently succeeds without inserting an entry into the MMIO RB tree.
Later, u-boot moves the block device BAR, so nothing is mapped at
0xdf000000, and then when FreeBSD reprograms BARs it triggers an
assertion failure because unregister_mem() isn't allowed to fail.

What's the right solution?  At a glance, QEMU appears to permit
overlapping mappings and has a priority-based scheme for deciding which
mapping a given access corresponds to.  I verified that u-boot doesn't
actually access the mappings in the window that the overlap, so it seems
pretty safe to allow overlapping mappings and handle access conflicts
with an assertion failure or so.  Is there some context I'm missing?
Should I look further into what u-boot is doing instead?  Thanks in
advance for any pointers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?ZimBn5Cv0ippsgTj>