From 759ed40d987b3e9a3f09eee5cfc2990754a2f421 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 6 Oct 2022 14:17:35 +0200 Subject: [PATCH] hw: implement MSI support for x86 Fix genodelabs/genode#4633 --- .../base-hw/src/core/irq_session_component.cc | 5 ++-- repos/base-hw/src/core/platform.cc | 1 + repos/base-hw/src/core/platform.h | 22 +++++++++------- .../src/core/spec/arm/platform_support.cc | 9 +++---- .../src/core/spec/riscv/platform_support.cc | 7 +++--- .../src/core/spec/x86_64/platform_support.cc | 25 +++++++++++++++++-- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/repos/base-hw/src/core/irq_session_component.cc b/repos/base-hw/src/core/irq_session_component.cc index 33d54b2f59..4f710b1df2 100644 --- a/repos/base-hw/src/core/irq_session_component.cc +++ b/repos/base-hw/src/core/irq_session_component.cc @@ -58,6 +58,7 @@ Irq_session_component::~Irq_session_component() using namespace Kernel; _irq_alloc.free((void *)(addr_t)_irq_number); + if (_is_msi) Platform::free_msi_vector(_address, _value); } @@ -72,10 +73,10 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc, Arg_string::find_arg(args, "device_config_phys").long_value(0); if (mmconf) { - _is_msi = - Platform::get_msi_params(mmconf, _address, _value, _irq_number); + _is_msi = Platform::alloc_msi_vector(_address, _value); if (!_is_msi) throw Service_denied(); + _irq_number = (unsigned) _value; } /* allocate interrupt */ diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc index 66d1146a89..e51cb2210d 100644 --- a/repos/base-hw/src/core/platform.cc +++ b/repos/base-hw/src/core/platform.cc @@ -161,6 +161,7 @@ void Platform::_init_platform_info() xml.node("kernel", [&] () { xml.attribute("name", "hw"); xml.attribute("acpi", true); + xml.attribute("msi", true); }); _init_additional_platform_info(xml); xml.node("affinity-space", [&] () { diff --git a/repos/base-hw/src/core/platform.h b/repos/base-hw/src/core/platform.h index 44f72754f9..8924242887 100644 --- a/repos/base-hw/src/core/platform.h +++ b/repos/base-hw/src/core/platform.h @@ -97,18 +97,22 @@ class Genode::Platform : public Genode::Platform_generic static long irq(long const user_irq); /** - * Get MSI-related parameters from device PCI config space + * Allocate MSI exception vector entry * - * \param mmconf PCI config space address of device - * \param address MSI address register value to use - * \param data MSI data register value to use - * \param irq_number IRQ to use + * \param address MSI address register value to use + * \param data MSI data register value to use * - * \return true if the device is MSI-capable, false if not + * \return true if the platform is MSI-capable, false if not */ - static bool get_msi_params(const addr_t mmconf, - addr_t &address, addr_t &data, - unsigned &irq_number); + static bool alloc_msi_vector(addr_t &address, addr_t &data); + + /** + * Allocate MSI exception vector entry + * + * \param address MSI address register value to free + * \param data MSI data register value to free + */ + static void free_msi_vector(addr_t address, addr_t data); static addr_t core_phys_addr(addr_t virt); diff --git a/repos/base-hw/src/core/spec/arm/platform_support.cc b/repos/base-hw/src/core/spec/arm/platform_support.cc index 5bef5904c3..8890fb0d3d 100644 --- a/repos/base-hw/src/core/spec/arm/platform_support.cc +++ b/repos/base-hw/src/core/spec/arm/platform_support.cc @@ -26,8 +26,7 @@ void Platform::_init_additional_platform_info(Genode::Xml_generator&) { } long Platform::irq(long const user_irq) { return user_irq; } -bool Platform::get_msi_params(const addr_t /* mmconf */, addr_t & /* address */, - addr_t & /* data */, unsigned & /* irq_number */) -{ - return false; -} +bool Platform::alloc_msi_vector(addr_t &, addr_t &) { return false; } + + +void Platform::free_msi_vector(addr_t, addr_t) { } diff --git a/repos/base-hw/src/core/spec/riscv/platform_support.cc b/repos/base-hw/src/core/spec/riscv/platform_support.cc index 702c1b0c35..d9cb1ada00 100644 --- a/repos/base-hw/src/core/spec/riscv/platform_support.cc +++ b/repos/base-hw/src/core/spec/riscv/platform_support.cc @@ -28,6 +28,7 @@ void Platform::_init_additional_platform_info(Genode::Xml_generator&) { } long Platform::irq(long const user_irq ) { return user_irq; } -bool Platform::get_msi_params(addr_t /* mmconf */, addr_t & /* address */, - addr_t & /* data */, unsigned & /* irq_number */) { - return false; } +bool Platform::alloc_msi_vector(addr_t &, addr_t &) { return false; } + + +void Platform::free_msi_vector(addr_t, addr_t) { } diff --git a/repos/base-hw/src/core/spec/x86_64/platform_support.cc b/repos/base-hw/src/core/spec/x86_64/platform_support.cc index 70bdf6a40d..ef53e5dec2 100644 --- a/repos/base-hw/src/core/spec/x86_64/platform_support.cc +++ b/repos/base-hw/src/core/spec/x86_64/platform_support.cc @@ -15,6 +15,7 @@ #include #include #include +#include using namespace Genode; @@ -60,8 +61,28 @@ void Platform::_init_additional_platform_info(Xml_generator &xml) } -bool Platform::get_msi_params(addr_t, addr_t &, addr_t &, unsigned &) { - return false; } +Genode::Bit_allocator<64> & msi_allocator() +{ + static Genode::Bit_allocator<64> msi_allocator; + return msi_allocator; +} + + +bool Platform::alloc_msi_vector(addr_t & address, addr_t & value) +{ + try { + address = Hw::Cpu_memory_map::lapic_phys_base(); + value = Board::Pic::IPI - 1 - msi_allocator().alloc(); + return true; + } catch(...) {} + return false; +} + + +void Platform::free_msi_vector(addr_t, addr_t value) +{ + msi_allocator().free(Board::Pic::IPI - 1 - value); +} Board::Serial::Serial(addr_t, size_t, unsigned baudrate)