mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
devices: vfio: Fix a msix table and msix pba table overlapping issue
An error occured when passthrough some nvme to a guest based on vfio: [ERROR:devices/src/pci/vfio_pci.rs:773] add_bar_mmap_msix failed: Out-of-space detected in MSIX Allocator Althrough the issue may only happen to some devices whose msix table overlaps with its msix pba table, as it was mentioned before[1], this situation must be covered by some validation test. Otherwise, it will block crosvm booting. [1] https://patchwork.kernel.org/project/qemu-devel/patch/099db937-3fa3-465e-9a23-a900df9adb7c@default/ BUG=b:1971693450 TEST=passthrough a nvme with a msix table overlapping the msix pba table, then boot Linux kernel and verify MSIX-capable passed-through devices work properly. Change-Id: I602dda95d4671682dc03478415f6a96d7c40ec6e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3152434 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
e32b55670b
commit
7458a3a19b
1 changed files with 9 additions and 2 deletions
|
@ -260,14 +260,21 @@ struct VfioMsixCap {
|
|||
impl VfioMsixCap {
|
||||
fn new(config: &VfioPciConfig, msix_cap_start: u32, vm_socket_irq: Tube) -> Self {
|
||||
let msix_ctl = config.read_config_word(msix_cap_start + PCI_MSIX_FLAGS);
|
||||
let table_size = (msix_ctl & PCI_MSIX_FLAGS_QSIZE) as u64 + 1;
|
||||
let table = config.read_config_dword(msix_cap_start + PCI_MSIX_TABLE);
|
||||
let table_pci_bar = table & PCI_MSIX_TABLE_BIR;
|
||||
let table_offset = (table & PCI_MSIX_TABLE_OFFSET) as u64;
|
||||
let table_size_bytes = table_size * MSIX_TABLE_ENTRIES_MODULO;
|
||||
let pba = config.read_config_dword(msix_cap_start + PCI_MSIX_PBA);
|
||||
let pba_pci_bar = pba & PCI_MSIX_PBA_BIR;
|
||||
let pba_offset = (pba & PCI_MSIX_PBA_OFFSET) as u64;
|
||||
|
||||
let mut table_size = (msix_ctl & PCI_MSIX_FLAGS_QSIZE) as u64 + 1;
|
||||
if table_pci_bar == pba_pci_bar
|
||||
&& (table_offset + table_size * MSIX_TABLE_ENTRIES_MODULO) > pba_offset
|
||||
{
|
||||
table_size = (pba_offset - table_offset) / MSIX_TABLE_ENTRIES_MODULO;
|
||||
}
|
||||
|
||||
let table_size_bytes = table_size * MSIX_TABLE_ENTRIES_MODULO;
|
||||
let pba_size_bytes = ((table_size + BITS_PER_PBA_ENTRY as u64 - 1)
|
||||
/ BITS_PER_PBA_ENTRY as u64)
|
||||
* MSIX_PBA_ENTRIES_MODULO;
|
||||
|
|
Loading…
Reference in a new issue