From 13abc33ec94d3a6187724c962ef948928fb6847e Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 15 Jan 2025 11:16:55 +0100 Subject: [PATCH] platform: be robust on IRQ creation failure In case invalid IRQ numbers are used (255 on x86), the IRQ session creation request may be denied and the platform driver is killed because of the uncatched exception, which must be avoided. Issue #5406 --- .../src/driver/platform/device_component.cc | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/repos/os/src/driver/platform/device_component.cc b/repos/os/src/driver/platform/device_component.cc index bd6d5a23f1..ed5d710a55 100644 --- a/repos/os/src/driver/platform/device_component.cc +++ b/repos/os/src/driver/platform/device_component.cc @@ -152,64 +152,66 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx) return remapped_irq; }; - _irq_registry.for_each([&] (Irq & irq) - { - if (irq.idx != idx) - return; + try { + _irq_registry.for_each([&] (Irq & irq) + { + if (irq.idx != idx) + return; - if (!irq.shared && !irq.irq.constructed()) { - addr_t pci_cfg_addr = 0; - Pci::Bdf bdf { 0, 0, 0 }; - if (irq.type != Irq_session::TYPE_LEGACY) { - if (_pci_config.constructed()) { - pci_cfg_addr = _pci_config->addr; - bdf = _pci_config->bdf; + if (!irq.shared && !irq.irq.constructed()) { + addr_t pci_cfg_addr = 0; + Pci::Bdf bdf { 0, 0, 0 }; + if (irq.type != Irq_session::TYPE_LEGACY) { + if (_pci_config.constructed()) { + pci_cfg_addr = _pci_config->addr; + bdf = _pci_config->bdf; + } else + error("MSI(-x) detected for device without pci-config!"); + + irq.irq.construct(_env, irq.number, pci_cfg_addr, irq.type); } else - error("MSI(-x) detected for device without pci-config!"); + irq.irq.construct(_env, irq.number, irq.mode, irq.polarity); - irq.irq.construct(_env, irq.number, pci_cfg_addr, irq.type); - } else - irq.irq.construct(_env, irq.number, irq.mode, irq.polarity); + /** + * Core/Kernel is and remains in control of the IRQ controller. When + * IRQ remapping is enabled, however, we need to modify the upper 32bit + * of the corresponding redirection table entry. This is save for + * base-hw as it never touches the upper 32bit after the initial setup. + */ + Irq_session::Info info = irq.irq->info(); + if (pci_cfg_addr && info.type == Irq_session::Info::MSI) + pci_msi_enable(_env, *this, pci_cfg_addr, + remapped_irq("", bdf, irq, info, Irq_config::Invalid()).session_info, + irq.type); + else + _session.irq_controller_registry().for_each([&] (Irq_controller & controller) { + if (!controller.handles_irq(irq.number)) return; - /** - * Core/Kernel is and remains in control of the IRQ controller. When - * IRQ remapping is enabled, however, we need to modify the upper 32bit - * of the corresponding redirection table entry. This is save for - * base-hw as it never touches the upper 32bit after the initial setup. - */ - Irq_session::Info info = irq.irq->info(); - if (pci_cfg_addr && info.type == Irq_session::Info::MSI) - pci_msi_enable(_env, *this, pci_cfg_addr, - remapped_irq("", bdf, irq, info, Irq_config::Invalid()).session_info, - irq.type); - else - _session.irq_controller_registry().for_each([&] (Irq_controller & controller) { - if (!controller.handles_irq(irq.number)) return; + remapped_irq(controller.iommu(), controller.bdf(), irq, info, + controller.irq_config(irq.number)); + controller.remap_irq(irq.number, irq.remapped_nbr); + }); + } - remapped_irq(controller.iommu(), controller.bdf(), irq, info, - controller.irq_config(irq.number)); - controller.remap_irq(irq.number, irq.remapped_nbr); + if (irq.shared && !irq.sirq.constructed()) + _device_model.with_shared_irq(irq.number, + [&] (Shared_interrupt & sirq) { + irq.sirq.construct(_env.ep().rpc_ep(), sirq, + irq.mode, irq.polarity); + + _session.irq_controller_registry().for_each([&] (Irq_controller & controller) { + if (!controller.handles_irq(irq.number)) return; + + remapped_irq(controller.iommu(), controller.bdf(), irq, + { Irq_session::Info::INVALID, 0, 0 }, + controller.irq_config(irq.number)); + controller.remap_irq(irq.number, irq.remapped_nbr); + }); }); - } - if (irq.shared && !irq.sirq.constructed()) - _device_model.with_shared_irq(irq.number, - [&] (Shared_interrupt & sirq) { - irq.sirq.construct(_env.ep().rpc_ep(), sirq, - irq.mode, irq.polarity); - - _session.irq_controller_registry().for_each([&] (Irq_controller & controller) { - if (!controller.handles_irq(irq.number)) return; - - remapped_irq(controller.iommu(), controller.bdf(), irq, - { Irq_session::Info::INVALID, 0, 0 }, - controller.irq_config(irq.number)); - controller.remap_irq(irq.number, irq.remapped_nbr); - }); - }); - - cap = irq.shared ? irq.sirq->cap() : irq.irq->cap(); - }); + cap = irq.shared ? irq.sirq->cap() : irq.irq->cap(); + }); + } catch (Service_denied) { error("irq could not be setup ", _device); } return cap; }