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:
+11
-5
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user