Kernel: Safely fail allocating zero sized BAR regions

Our device discovery thinks vmware's audio device is AC97 and allocating
one of the BARs leads to zero sized allocation -> panic from page table
as it tries to allocate 0 pages. Now we gracefully handle these regions
and fail to allocate the BAR
This commit is contained in:
2026-08-23 15:44:12 +03:00
parent 7e7ca3d929
commit f163dacce5
+11 -5
View File
@@ -912,10 +912,10 @@ namespace Kernel::PCI
} }
// disable io/mem space while reading bar // disable io/mem space while reading bar
uint16_t command = device.read_word(PCI_REG_COMMAND); const uint16_t command = device.read_word(PCI_REG_COMMAND);
device.write_word(PCI_REG_COMMAND, command & ~(PCI_CMD_IO_SPACE | PCI_CMD_MEM_SPACE)); device.write_word(PCI_REG_COMMAND, command & ~(PCI_CMD_IO_SPACE | PCI_CMD_MEM_SPACE));
uint8_t offset = 0x10 + bar_num * 4; const uint8_t offset = 0x10 + bar_num * 4;
uint64_t addr = device.read_dword(offset); uint64_t addr = device.read_dword(offset);
@@ -924,6 +924,13 @@ namespace Kernel::PCI
size = ~size + 1; size = ~size + 1;
device.write_dword(offset, addr); device.write_dword(offset, addr);
if (size == 0)
{
device.write_word(PCI_REG_COMMAND, command);
dwarnln("BAR{} has size 0", bar_num);
return BAN::Error::from_errno(EINVAL);
}
// determine bar type // determine bar type
BarType type = BarType::INVALID; BarType type = BarType::INVALID;
if (addr & 1) if (addr & 1)
@@ -956,8 +963,7 @@ namespace Kernel::PCI
TRY(region->initialize()); TRY(region->initialize());
// restore old command register and enable correct IO/MEM space // restore old command register and enable correct IO/MEM space
command |= (type == BarType::IO) ? PCI_CMD_IO_SPACE : PCI_CMD_MEM_SPACE; device.write_word(PCI_REG_COMMAND, command | ((type == BarType::IO) ? PCI_CMD_IO_SPACE : PCI_CMD_MEM_SPACE));
device.write_word(PCI_REG_COMMAND, command);
#if DEBUG_PCI #if DEBUG_PCI
dprintln("created BAR region for PCI {2H}:{2H}.{2H}", dprintln("created BAR region for PCI {2H}:{2H}.{2H}",
@@ -997,7 +1003,7 @@ namespace Kernel::PCI
if (m_type == BarType::IO) if (m_type == BarType::IO)
return {}; return {};
size_t needed_pages = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); const size_t needed_pages = BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE);
m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET); m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(needed_pages, KERNEL_OFFSET);
if (m_vaddr == 0) if (m_vaddr == 0)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);