Kernel: Fix interrupt system

I had not understood how MSIs work and I was unnecessarily routing them
through IOAPIC. This is not necessary and should not be done :D

Also MSIs were reserving interrupts that IOAPIC was capable of
generating. Now IOAPIC and MSIs use different set of interrupts so
IOAPIC can use more interrupts if needed.
This commit is contained in:
2024-09-27 15:31:31 +03:00
parent e4982a1a5c
commit 2d11ce9669
25 changed files with 618 additions and 199 deletions

View File

@@ -55,6 +55,15 @@ namespace Kernel::PCI
class Device
{
public:
enum class InterruptMechanism
{
NONE,
MSIX,
MSI,
PIN,
};
public:
Device() = default;
@@ -84,8 +93,9 @@ namespace Kernel::PCI
uint16_t vendor_id() const { return m_vendor_id; }
uint16_t device_id() const { return m_device_id; }
BAN::ErrorOr<void> reserve_irqs(uint8_t count);
uint8_t get_irq(uint8_t index);
uint8_t get_interrupt(uint8_t index) const;
BAN::ErrorOr<void> reserve_interrupts(uint8_t count);
void enable_interrupt(uint8_t index, Interruptable&);
BAN::ErrorOr<BAN::UniqPtr<BarRegion>> allocate_bar_region(uint8_t bar_num);
@@ -123,8 +133,9 @@ namespace Kernel::PCI
uint16_t m_vendor_id { 0 };
uint16_t m_device_id { 0 };
uint32_t m_reserved_irqs { 0 };
uint8_t m_reserved_irq_count { 0 };
InterruptMechanism m_interrupt_mechanism { InterruptMechanism::NONE };
uint8_t m_reserved_interrupts[0x100 / 8] {};
uint8_t m_reserved_interrupt_count { 0 };
BAN::Optional<uint8_t> m_offset_msi;
BAN::Optional<uint8_t> m_offset_msi_x;
@@ -159,6 +170,8 @@ namespace Kernel::PCI
void write_config_word(uint8_t bus, uint8_t dev, uint8_t func, uint8_t offset, uint16_t value);
void write_config_byte(uint8_t bus, uint8_t dev, uint8_t func, uint8_t offset, uint8_t value);
BAN::Optional<uint8_t> reserve_msi();
private:
PCIManager() : m_bus_pcie_paddr(0) {}
void check_function(uint8_t bus, uint8_t dev, uint8_t func);
@@ -168,10 +181,14 @@ namespace Kernel::PCI
void initialize_impl();
private:
static constexpr uint8_t m_msi_count = IRQ_SYSCALL - IRQ_MSI_BASE;
using PCIBus = BAN::Array<BAN::Array<Device, 8>, 32>;
BAN::Array<PCIBus, 256> m_buses;
BAN::Array<paddr_t, 256> m_bus_pcie_paddr;
bool m_is_pcie { false };
BAN::Array<PCIBus, 256> m_buses;
BAN::Array<paddr_t, 256> m_bus_pcie_paddr;
bool m_is_pcie { false };
SpinLock m_reserved_msi_lock;
BAN::Array<uint8_t, m_msi_count / 8> m_reserved_msi_bitmap;
};
}