Kernel/PCI: Cache more details about PCI devices when enumerating them

There's no good reason to fetch these values each time we need them.
This commit is contained in:
Liav A 2021-09-23 09:05:34 +03:00 committed by Andreas Kling
parent e22d9dc360
commit 82bb08a15c
Notes: sideshowbarker 2024-07-18 03:21:21 +09:00
14 changed files with 85 additions and 41 deletions

View file

@ -17,7 +17,7 @@ u8 read8(Address address, u32 field) { return Access::the().read8_field(address,
u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); } u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); }
u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); } u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); }
void enumerate(Function<void(Address, ID)> callback) void enumerate(Function<void(Address, PhysicalID const&)> callback)
{ {
Access::the().fast_enumerate(callback); Access::the().fast_enumerate(callback);
} }

View file

@ -19,7 +19,7 @@ u32 read32(Address address, u32 field);
ID get_id(PCI::Address); ID get_id(PCI::Address);
bool is_io_space_enabled(Address); bool is_io_space_enabled(Address);
void enumerate(Function<void(Address, ID)> callback); void enumerate(Function<void(Address, PhysicalID const&)> callback);
void enable_interrupt_line(Address); void enable_interrupt_line(Address);
void disable_interrupt_line(Address); void disable_interrupt_line(Address);
u8 get_interrupt_line(Address); u8 get_interrupt_line(Address);

View file

@ -381,7 +381,14 @@ UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u
Address address(0, bus, device, function); Address address(0, bus, device, function);
auto read_type = (read8_field(address, PCI_CLASS) << 8u) | read8_field(address, PCI_SUBCLASS); auto read_type = (read8_field(address, PCI_CLASS) << 8u) | read8_field(address, PCI_SUBCLASS);
if (type == -1 || type == read_type) { if (type == -1 || type == read_type) {
m_physical_ids.append(PhysicalID { address, { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) }, get_capabilities(address) }); PCI::ID id = { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) };
ClassCode class_code = read8_field(address, PCI_CLASS);
SubclassCode subclass_code = read8_field(address, PCI_SUBCLASS);
ProgrammingInterface prog_if = read8_field(address, PCI_PROG_IF);
RevisionID revision_id = read8_field(address, PCI_REVISION_ID);
SubsystemID subsystem_id = read16_field(address, PCI_SUBSYSTEM_ID);
SubsystemVendorID subsystem_vendor_id = read16_field(address, PCI_SUBSYSTEM_VENDOR_ID);
m_physical_ids.append(PhysicalID { address, id, revision_id, class_code, subclass_code, prog_if, subsystem_id, subsystem_vendor_id, get_capabilities(address) });
} }
if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) { if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) {
@ -416,12 +423,12 @@ UNMAP_AFTER_INIT void Access::enumerate_bus(int type, u8 bus, bool recursive)
enumerate_device(type, bus, device, recursive); enumerate_device(type, bus, device, recursive);
} }
void Access::fast_enumerate(Function<void(Address, ID)>& callback) const void Access::fast_enumerate(Function<void(Address, PhysicalID const&)>& callback) const
{ {
MutexLocker locker(m_scan_lock); MutexLocker locker(m_scan_lock);
VERIFY(!m_physical_ids.is_empty()); VERIFY(!m_physical_ids.is_empty());
for (auto& physical_id : m_physical_ids) { for (auto& physical_id : m_physical_ids) {
callback(physical_id.address(), physical_id.id()); callback(physical_id.address(), physical_id);
} }
} }

View file

@ -25,7 +25,7 @@ public:
static bool initialize_for_memory_access(PhysicalAddress mcfg_table); static bool initialize_for_memory_access(PhysicalAddress mcfg_table);
static bool initialize_for_io_access(); static bool initialize_for_io_access();
void fast_enumerate(Function<void(Address, ID)>&) const; void fast_enumerate(Function<void(Address, PhysicalID const&)>&) const;
void rescan_hardware(); void rescan_hardware();
static Access& the(); static Access& the();

View file

@ -181,11 +181,25 @@ private:
const u8 m_ptr; const u8 m_ptr;
}; };
TYPEDEF_DISTINCT_ORDERED_ID(u8, ClassCode);
TYPEDEF_DISTINCT_ORDERED_ID(u8, SubclassCode);
TYPEDEF_DISTINCT_ORDERED_ID(u8, ProgrammingInterface);
TYPEDEF_DISTINCT_ORDERED_ID(u8, RevisionID);
TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemID);
TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemVendorID);
class Access;
class PhysicalID { class PhysicalID {
public: public:
PhysicalID(Address address, ID id, Vector<Capability> capabilities) PhysicalID(Address address, ID id, RevisionID revision_id, ClassCode class_code, SubclassCode subclass_code, ProgrammingInterface prog_if, SubsystemID subsystem_id, SubsystemVendorID subsystem_vendor_id, Vector<Capability> capabilities)
: m_address(address) : m_address(address)
, m_id(id) , m_id(id)
, m_revision_id(revision_id)
, m_class_code(class_code)
, m_subclass_code(subclass_code)
, m_prog_if(prog_if)
, m_subsystem_id(subsystem_id)
, m_subsystem_vendor_id(subsystem_vendor_id)
, m_capabilities(capabilities) , m_capabilities(capabilities)
{ {
if constexpr (PCI_DEBUG) { if constexpr (PCI_DEBUG) {
@ -198,13 +212,36 @@ public:
const ID& id() const { return m_id; } const ID& id() const { return m_id; }
const Address& address() const { return m_address; } const Address& address() const { return m_address; }
RevisionID revision_id() const { return m_revision_id; }
ClassCode class_code() const { return m_class_code; }
SubclassCode subclass_code() const { return m_subclass_code; }
ProgrammingInterface prog_if() const { return m_prog_if; }
SubsystemID subsystem_id() const { return m_subsystem_id; }
SubsystemVendorID subsystem_vendor_id() const { return m_subsystem_vendor_id; }
void apply_subclass_code_change(Badge<Access>, SubclassCode new_subclass)
{
m_subclass_code = new_subclass;
}
void apply_prog_if_change(Badge<Access>, ProgrammingInterface new_progif)
{
m_prog_if = new_progif;
}
private: private:
Address m_address; Address m_address;
ID m_id; ID m_id;
RevisionID m_revision_id;
ClassCode m_class_code;
SubclassCode m_subclass_code;
ProgrammingInterface m_prog_if;
SubsystemID m_subsystem_id;
SubsystemVendorID m_subsystem_vendor_id;
Vector<Capability> m_capabilities; Vector<Capability> m_capabilities;
}; };
class Access;
class Domain; class Domain;
class Device; class Device;
} }

View file

@ -56,8 +56,8 @@ UNMAP_AFTER_INIT void initialize()
PCI::PCIBusSysFSDirectory::initialize(); PCI::PCIBusSysFSDirectory::initialize();
PCI::enumerate([&](const Address& address, ID id) { PCI::enumerate([&](const Address& address, PhysicalID const& physical_id) {
dmesgln("{} {}", address, id); dmesgln("{} {}", address, physical_id.id());
}); });
} }

View file

@ -41,7 +41,7 @@ UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize()
UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory() UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory()
: SysFSDirectory("pci", SysFSComponentRegistry::the().buses_directory()) : SysFSDirectory("pci", SysFSComponentRegistry::the().buses_directory())
{ {
PCI::enumerate([&](const Address& address, ID) { PCI::enumerate([&](const Address& address, PhysicalID const&) {
auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address); auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address);
m_components.append(pci_device); m_components.append(pci_device);
}); });

View file

@ -27,10 +27,10 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
if (kernel_command_line().disable_usb()) if (kernel_command_line().disable_usb())
return; return;
PCI::enumerate([this](PCI::Address const& address, PCI::ID) { PCI::enumerate([this](PCI::Address const& address, PCI::PhysicalID const& physical_id) {
if (!(PCI::get_class(address) == 0xc && PCI::get_subclass(address) == 0x3)) if (!(physical_id.class_code().value() == 0xc && physical_id.subclass_code().value() == 0x3))
return; return;
if (PCI::get_programming_interface(address) == 0x0) { if (physical_id.prog_if().value() == 0x0) {
if (kernel_command_line().disable_uhci_controller()) if (kernel_command_line().disable_uhci_controller())
return; return;
@ -40,22 +40,22 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
return; return;
} }
if (PCI::get_programming_interface(address) == 0x10) { if (physical_id.prog_if().value() == 0x10) {
dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", address); dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", address);
return; return;
} }
if (PCI::get_programming_interface(address) == 0x20) { if (physical_id.prog_if().value() == 0x20) {
dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", address); dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", address);
return; return;
} }
if (PCI::get_programming_interface(address) == 0x30) { if (physical_id.prog_if().value() == 0x30) {
dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", address); dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", address);
return; return;
} }
dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, PCI::get_programming_interface(address)); dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, physical_id.prog_if().value());
}); });
} }

View file

@ -18,13 +18,13 @@ UNMAP_AFTER_INIT void detect()
{ {
if (kernel_command_line().disable_virtio()) if (kernel_command_line().disable_virtio())
return; return;
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (address.is_null() || id.is_null()) if (address.is_null() || physical_id.id().is_null())
return; return;
// TODO: We should also be checking that the device_id is in between 0x1000 - 0x107F inclusive // TODO: We should also be checking that the device_id is in between 0x1000 - 0x107F inclusive
if (id.vendor_id != PCI::VendorID::VirtIO) if (physical_id.id().vendor_id != PCI::VendorID::VirtIO)
return; return;
switch (id.device_id) { switch (physical_id.id().device_id) {
case PCI::DeviceID::VirtIOConsole: { case PCI::DeviceID::VirtIOConsole: {
auto& console = Console::must_create(address).leak_ref(); auto& console = Console::must_create(address).leak_ref();
console.initialize(); console.initialize();
@ -40,7 +40,7 @@ UNMAP_AFTER_INIT void detect()
break; break;
} }
default: default:
dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", id.device_id); dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", physical_id.id().device_id);
break; break;
} }
}); });

View file

@ -15,12 +15,12 @@ static SerialDevice* s_the = nullptr;
UNMAP_AFTER_INIT void PCISerialDevice::detect() UNMAP_AFTER_INIT void PCISerialDevice::detect()
{ {
size_t current_device_minor = 68; size_t current_device_minor = 68;
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (address.is_null()) if (address.is_null())
return; return;
for (auto& board_definition : board_definitions) { for (auto& board_definition : board_definitions) {
if (board_definition.device_id != id) if (board_definition.device_id != physical_id.id())
continue; continue;
auto bar_base = PCI::get_BAR(address, board_definition.pci_bar) & ~1; auto bar_base = PCI::get_BAR(address, board_definition.pci_bar) & ~1;

View file

@ -614,19 +614,19 @@ private:
virtual KResult try_generate(KBufferBuilder& builder) override virtual KResult try_generate(KBufferBuilder& builder) override
{ {
JsonArraySerializer array { builder }; JsonArraySerializer array { builder };
PCI::enumerate([&array](PCI::Address address, PCI::ID id) { PCI::enumerate([&array](PCI::Address address, PCI::PhysicalID const& physical_id) {
auto obj = array.add_object(); auto obj = array.add_object();
obj.add("domain", address.domain()); obj.add("domain", address.domain());
obj.add("bus", address.bus()); obj.add("bus", address.bus());
obj.add("device", address.device()); obj.add("device", address.device());
obj.add("function", address.function()); obj.add("function", address.function());
obj.add("vendor_id", id.vendor_id); obj.add("vendor_id", physical_id.id().vendor_id);
obj.add("device_id", id.device_id); obj.add("device_id", physical_id.id().device_id);
obj.add("revision_id", PCI::get_revision_id(address)); obj.add("revision_id", physical_id.revision_id().value());
obj.add("subclass", PCI::get_subclass(address)); obj.add("subclass", physical_id.subclass_code().value());
obj.add("class", PCI::get_class(address)); obj.add("class", physical_id.class_code().value());
obj.add("subsystem_id", PCI::get_subsystem_id(address)); obj.add("subsystem_id", physical_id.subsystem_id().value());
obj.add("subsystem_vendor_id", PCI::get_subsystem_vendor_id(address)); obj.add("subsystem_vendor_id", physical_id.subsystem_vendor_id().value());
}); });
array.finish(); array.finish();
return KSuccess; return KSuccess;

View file

@ -179,13 +179,13 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
dbgln("Forcing no initialization of framebuffer devices"); dbgln("Forcing no initialization of framebuffer devices");
} }
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
// Note: Each graphics controller will try to set its native screen resolution // Note: Each graphics controller will try to set its native screen resolution
// upon creation. Later on, if we don't want to have framebuffer devices, a // upon creation. Later on, if we don't want to have framebuffer devices, a
// framebuffer console will take the control instead. // framebuffer console will take the control instead.
if (!is_vga_compatible_pci_device(address) && !is_display_controller_pci_device(address)) if (!is_vga_compatible_pci_device(address) && !is_display_controller_pci_device(address))
return; return;
determine_and_initialize_graphics_device(address, id); determine_and_initialize_graphics_device(address, physical_id.id());
}); });
if (m_graphics_devices.is_empty()) { if (m_graphics_devices.is_empty()) {

View file

@ -91,9 +91,9 @@ UNMAP_AFTER_INIT RefPtr<NetworkAdapter> NetworkingManagement::determine_network_
bool NetworkingManagement::initialize() bool NetworkingManagement::initialize()
{ {
if (!kernel_command_line().is_physical_networking_disabled()) { if (!kernel_command_line().is_physical_networking_disabled()) {
PCI::enumerate([&](const PCI::Address& address, PCI::ID) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
// Note: PCI class 2 is the class of Network devices // Note: PCI class 2 is the class of Network devices
if (PCI::get_class(address) != 0x02) if (physical_id.class_code().value() != 0x02)
return; return;
if (auto adapter = determine_network_device(address); !adapter.is_null()) if (auto adapter = determine_network_device(address); !adapter.is_null())
m_adapters.append(adapter.release_nonnull()); m_adapters.append(adapter.release_nonnull());

View file

@ -44,14 +44,14 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
VERIFY(m_controllers.is_empty()); VERIFY(m_controllers.is_empty());
if (!kernel_command_line().disable_physical_storage()) { if (!kernel_command_line().disable_physical_storage()) {
if (kernel_command_line().is_ide_enabled()) { if (kernel_command_line().is_ide_enabled()) {
PCI::enumerate([&](const PCI::Address& address, PCI::ID) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_IDE_CTRL_SUBCLASS_ID) { if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_IDE_CTRL_SUBCLASS_ID) {
m_controllers.append(IDEController::initialize(address, force_pio)); m_controllers.append(IDEController::initialize(address, force_pio));
} }
}); });
} }
PCI::enumerate([&](const PCI::Address& address, PCI::ID) { PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_SATA_CTRL_SUBCLASS_ID && PCI::get_programming_interface(address) == PCI_AHCI_IF_PROGIF) { if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_SATA_CTRL_SUBCLASS_ID && physical_id.prog_if().value() == PCI_AHCI_IF_PROGIF) {
m_controllers.append(AHCIController::initialize(address)); m_controllers.append(AHCIController::initialize(address));
} }
}); });