From d0fbaf790a57df7737e04dfeeb02687bdada7ac0 Mon Sep 17 00:00:00 2001 From: Pankaj Raghav Date: Fri, 28 Apr 2023 15:16:20 +0200 Subject: [PATCH] Kernel: Add MSIxInfo struct to PCI DeviceIdentifier Add a struct named MSIxInfo that stores all the relevant MSIx information as a part of PCI DeviceIdentifier struct. Populate the MSIx struct during the PCI device init. As the DeviceIdentifier struct need to populate MSIx info, don't mark DeviceIdentifier as const in the PCI::Device class. --- Kernel/Bus/PCI/Definitions.h | 25 +++++++++++++++++++++++++ Kernel/Bus/PCI/Device.cpp | 1 + Kernel/Bus/PCI/Device.h | 2 +- Kernel/Bus/PCI/DeviceIdentifier.cpp | 12 ++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/Kernel/Bus/PCI/Definitions.h b/Kernel/Bus/PCI/Definitions.h index 8591e3f61e..4825268dec 100644 --- a/Kernel/Bus/PCI/Definitions.h +++ b/Kernel/Bus/PCI/Definitions.h @@ -79,6 +79,9 @@ static constexpr size_t mmio_device_space_size = 4096; static constexpr u16 none_value = 0xffff; static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice) * to_underlying(Limits::MaxDevicesPerBus); static constexpr u32 bar_address_mask = 0xfffffff0; +static constexpr u16 msix_control_table_mask = 0x07ff; +static constexpr u8 msix_table_bir_mask = 0x7; +static constexpr u16 msix_table_offset_mask = 0xfff8; // Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf enum class ClassID { @@ -319,6 +322,22 @@ protected: Vector m_capabilities; }; +class MSIxInfo { +public: + MSIxInfo(u16 table_size, u8 table_bar, u32 table_offset) + : table_size(table_size) + , table_bar(table_bar) + , table_offset(table_offset) + { + } + + MSIxInfo() = default; + + u16 table_size {}; + u8 table_bar {}; + u32 table_offset {}; +}; + class DeviceIdentifier : public RefCounted , public EnumerableDeviceIdentifier { @@ -327,6 +346,11 @@ class DeviceIdentifier public: static ErrorOr> from_enumerable_identifier(EnumerableDeviceIdentifier const& other_identifier); + void initialize(); + bool is_msix_capable() const { return m_msix_info.table_size > 0; } + u8 get_msix_table_bar() const { return m_msix_info.table_bar; } + u32 get_msix_table_offset() const { return m_msix_info.table_offset; } + Spinlock& operation_lock() { return m_operation_lock; } Spinlock& operation_lock() const { return m_operation_lock; } @@ -349,6 +373,7 @@ private: } mutable Spinlock m_operation_lock; + MSIxInfo m_msix_info {}; }; class Domain; diff --git a/Kernel/Bus/PCI/Device.cpp b/Kernel/Bus/PCI/Device.cpp index 6f0149d177..28761b2ca5 100644 --- a/Kernel/Bus/PCI/Device.cpp +++ b/Kernel/Bus/PCI/Device.cpp @@ -13,6 +13,7 @@ namespace Kernel::PCI { Device::Device(DeviceIdentifier const& pci_identifier) : m_pci_identifier(pci_identifier) { + m_pci_identifier->initialize(); } bool Device::is_msi_capable() const diff --git a/Kernel/Bus/PCI/Device.h b/Kernel/Bus/PCI/Device.h index 1f6a22877e..bb75f75f0a 100644 --- a/Kernel/Bus/PCI/Device.h +++ b/Kernel/Bus/PCI/Device.h @@ -38,7 +38,7 @@ protected: explicit Device(DeviceIdentifier const& pci_identifier); private: - NonnullRefPtr const m_pci_identifier; + NonnullRefPtr const m_pci_identifier; }; template diff --git a/Kernel/Bus/PCI/DeviceIdentifier.cpp b/Kernel/Bus/PCI/DeviceIdentifier.cpp index 785dfebff8..ee07737402 100644 --- a/Kernel/Bus/PCI/DeviceIdentifier.cpp +++ b/Kernel/Bus/PCI/DeviceIdentifier.cpp @@ -17,4 +17,16 @@ ErrorOr> DeviceIdentifier::from_enumerable_ident return adopt_nonnull_ref_or_enomem(new (nothrow) DeviceIdentifier(other_identifier)); } +void DeviceIdentifier::initialize() +{ + for (auto cap : capabilities()) { + if (cap.id() == PCI::Capabilities::ID::MSIX) { + auto msix_bir_bar = (cap.read8(4) & msix_table_bir_mask); + auto msix_bir_offset = (cap.read32(4) & msix_table_offset_mask); + auto msix_count = (cap.read16(2) & msix_control_table_mask) + 1; + m_msix_info = MSIxInfo(msix_count, msix_bir_bar, msix_bir_offset); + } + } +} + }